llvm-hs (empty) → 4.0.0.0
raw patch · 162 files changed
+14931/−0 lines, 162 filesdep +QuickCheckdep +arraydep +basebuild-type:Customsetup-changed
Dependencies added: QuickCheck, array, base, bytestring, containers, llvm-hs, llvm-hs-pure, mtl, parsec, pretty-show, semigroups, tasty, tasty-hunit, tasty-quickcheck, template-haskell, temporary, transformers, transformers-compat, utf8-string
Files
- LICENSE +30/−0
- Setup.hs +189/−0
- llvm-hs.cabal +273/−0
- src/Control/Monad/AnyCont.hs +30/−0
- src/Control/Monad/AnyCont/Class.hs +54/−0
- src/Control/Monad/Trans/AnyCont.hs +40/−0
- src/LLVM.hs +7/−0
- src/LLVM/Analysis.hs +8/−0
- src/LLVM/CodeGenOpt.hs +12/−0
- src/LLVM/CodeModel.hs +14/−0
- src/LLVM/CommandLine.hs +8/−0
- src/LLVM/Context.hs +7/−0
- src/LLVM/Diagnostic.hs +33/−0
- src/LLVM/ExecutionEngine.hs +8/−0
- src/LLVM/Internal/Analysis.hs +24/−0
- src/LLVM/Internal/Atomicity.hs +49/−0
- src/LLVM/Internal/Attribute.hs +279/−0
- src/LLVM/Internal/BasicBlock.hs +27/−0
- src/LLVM/Internal/CallingConvention.hs +71/−0
- src/LLVM/Internal/Coding.hs +140/−0
- src/LLVM/Internal/CommandLine.hs +23/−0
- src/LLVM/Internal/Constant.hs +248/−0
- src/LLVM/Internal/Context.hs +20/−0
- src/LLVM/Internal/DataLayout.hs +23/−0
- src/LLVM/Internal/DecodeAST.hs +172/−0
- src/LLVM/Internal/Diagnostic.hs +40/−0
- src/LLVM/Internal/EncodeAST.hs +159/−0
- src/LLVM/Internal/ExecutionEngine.hs +134/−0
- src/LLVM/Internal/FFI/Analysis.h +11/−0
- src/LLVM/Internal/FFI/Analysis.hs +15/−0
- src/LLVM/Internal/FFI/Assembly.hs +29/−0
- src/LLVM/Internal/FFI/AssemblyC.cpp +28/−0
- src/LLVM/Internal/FFI/Attribute.h +69/−0
- src/LLVM/Internal/FFI/Attribute.hs +143/−0
- src/LLVM/Internal/FFI/AttributeC.cpp +145/−0
- src/LLVM/Internal/FFI/AttributeC.hpp +24/−0
- src/LLVM/Internal/FFI/BasicBlock.hs +34/−0
- src/LLVM/Internal/FFI/BinaryOperator.h +16/−0
- src/LLVM/Internal/FFI/BinaryOperator.hs +30/−0
- src/LLVM/Internal/FFI/Bitcode.hs +26/−0
- src/LLVM/Internal/FFI/BitcodeC.cpp +34/−0
- src/LLVM/Internal/FFI/Builder.hs +184/−0
- src/LLVM/Internal/FFI/BuilderC.cpp +223/−0
- src/LLVM/Internal/FFI/ByteRangeCallback.hs +14/−0
- src/LLVM/Internal/FFI/CallingConvention.h +35/−0
- src/LLVM/Internal/FFI/CallingConventionC.cpp +10/−0
- src/LLVM/Internal/FFI/Cleanup.hs +83/−0
- src/LLVM/Internal/FFI/CommandLine.hs +15/−0
- src/LLVM/Internal/FFI/CommandLineC.cpp +12/−0
- src/LLVM/Internal/FFI/Constant.h +20/−0
- src/LLVM/Internal/FFI/Constant.hs +145/−0
- src/LLVM/Internal/FFI/ConstantC.cpp +114/−0
- src/LLVM/Internal/FFI/Context.hs +28/−0
- src/LLVM/Internal/FFI/DataLayout.hs +26/−0
- src/LLVM/Internal/FFI/ExecutionEngine.hs +71/−0
- src/LLVM/Internal/FFI/ExecutionEngineC.cpp +30/−0
- src/LLVM/Internal/FFI/Function.hs +72/−0
- src/LLVM/Internal/FFI/FunctionC.cpp +41/−0
- src/LLVM/Internal/FFI/GlobalAlias.hs +26/−0
- src/LLVM/Internal/FFI/GlobalAliasC.cpp +22/−0
- src/LLVM/Internal/FFI/GlobalValue.h +58/−0
- src/LLVM/Internal/FFI/GlobalValue.hs +79/−0
- src/LLVM/Internal/FFI/GlobalValueC.cpp +87/−0
- src/LLVM/Internal/FFI/GlobalVariable.hs +31/−0
- src/LLVM/Internal/FFI/InlineAssembly.h +14/−0
- src/LLVM/Internal/FFI/InlineAssembly.hs +35/−0
- src/LLVM/Internal/FFI/InlineAssemblyC.cpp +73/−0
- src/LLVM/Internal/FFI/Instruction.h +67/−0
- src/LLVM/Internal/FFI/Instruction.hs +181/−0
- src/LLVM/Internal/FFI/InstructionC.cpp +323/−0
- src/LLVM/Internal/FFI/InstructionDefs.hsc +61/−0
- src/LLVM/Internal/FFI/Iterate.hs +13/−0
- src/LLVM/Internal/FFI/LLVMCTypes.hsc +266/−0
- src/LLVM/Internal/FFI/LibFunc.h +332/−0
- src/LLVM/Internal/FFI/MemoryBuffer.hs +28/−0
- src/LLVM/Internal/FFI/Metadata.hpp +11/−0
- src/LLVM/Internal/FFI/Metadata.hs +93/−0
- src/LLVM/Internal/FFI/MetadataC.cpp +151/−0
- src/LLVM/Internal/FFI/Module.hs +103/−0
- src/LLVM/Internal/FFI/ModuleC.cpp +70/−0
- src/LLVM/Internal/FFI/OrcJIT.h +15/−0
- src/LLVM/Internal/FFI/OrcJIT.hs +51/−0
- src/LLVM/Internal/FFI/OrcJIT/CompileOnDemandLayer.hs +74/−0
- src/LLVM/Internal/FFI/OrcJIT/IRCompileLayer.hs +36/−0
- src/LLVM/Internal/FFI/OrcJITC.cpp +256/−0
- src/LLVM/Internal/FFI/PassManager.hs +134/−0
- src/LLVM/Internal/FFI/PassManagerC.cpp +248/−0
- src/LLVM/Internal/FFI/PtrHierarchy.hs +134/−0
- src/LLVM/Internal/FFI/RawOStream.hs +35/−0
- src/LLVM/Internal/FFI/RawOStreamC.cpp +36/−0
- src/LLVM/Internal/FFI/SMDiagnostic.h +15/−0
- src/LLVM/Internal/FFI/SMDiagnostic.hs +40/−0
- src/LLVM/Internal/FFI/SMDiagnosticC.cpp +42/−0
- src/LLVM/Internal/FFI/Target.h +71/−0
- src/LLVM/Internal/FFI/Target.hpp +11/−0
- src/LLVM/Internal/FFI/Target.hs +141/−0
- src/LLVM/Internal/FFI/TargetC.cpp +319/−0
- src/LLVM/Internal/FFI/Threading.hs +13/−0
- src/LLVM/Internal/FFI/Transforms.hs +76/−0
- src/LLVM/Internal/FFI/Type.h +23/−0
- src/LLVM/Internal/FFI/Type.hs +152/−0
- src/LLVM/Internal/FFI/TypeC.cpp +42/−0
- src/LLVM/Internal/FFI/User.hs +38/−0
- src/LLVM/Internal/FFI/Value.h +32/−0
- src/LLVM/Internal/FFI/Value.hs +41/−0
- src/LLVM/Internal/FFI/ValueC.cpp +30/−0
- src/LLVM/Internal/FastMathFlags.hs +51/−0
- src/LLVM/Internal/FloatingPointPredicate.hs +29/−0
- src/LLVM/Internal/Function.hs +70/−0
- src/LLVM/Internal/Global.hs +146/−0
- src/LLVM/Internal/Inject.hs +11/−0
- src/LLVM/Internal/InlineAssembly.hs +68/−0
- src/LLVM/Internal/Instruction.hs +607/−0
- src/LLVM/Internal/InstructionDefs.hs +71/−0
- src/LLVM/Internal/IntegerPredicate.hs +23/−0
- src/LLVM/Internal/LibraryFunction.hsc +37/−0
- src/LLVM/Internal/MemoryBuffer.hs +57/−0
- src/LLVM/Internal/Metadata.hs +56/−0
- src/LLVM/Internal/Module.hs +526/−0
- src/LLVM/Internal/Operand.hs +131/−0
- src/LLVM/Internal/OrcJIT.hs +107/−0
- src/LLVM/Internal/OrcJIT/CompileOnDemandLayer.hs +146/−0
- src/LLVM/Internal/OrcJIT/IRCompileLayer.hs +74/−0
- src/LLVM/Internal/PassManager.hs +147/−0
- src/LLVM/Internal/RMWOperation.hs +25/−0
- src/LLVM/Internal/RawOStream.hs +79/−0
- src/LLVM/Internal/String.hs +61/−0
- src/LLVM/Internal/TailCallKind.hs +18/−0
- src/LLVM/Internal/Target.hs +314/−0
- src/LLVM/Internal/Threading.hs +13/−0
- src/LLVM/Internal/Type.hs +164/−0
- src/LLVM/Internal/Value.hs +24/−0
- src/LLVM/Module.hs +27/−0
- src/LLVM/OrcJIT.hs +11/−0
- src/LLVM/OrcJIT/CompileOnDemandLayer.hs +14/−0
- src/LLVM/OrcJIT/IRCompileLayer.hs +10/−0
- src/LLVM/PassManager.hs +14/−0
- src/LLVM/Relocation.hs +12/−0
- src/LLVM/Target.hs +22/−0
- src/LLVM/Target/LibraryFunction.hs +7/−0
- src/LLVM/Target/Options.hs +41/−0
- src/LLVM/Threading.hs +24/−0
- src/LLVM/Transforms.hs +197/−0
- test/LLVM/Test/Analysis.hs +113/−0
- test/LLVM/Test/CallingConvention.hs +57/−0
- test/LLVM/Test/Constants.hs +184/−0
- test/LLVM/Test/DataLayout.hs +86/−0
- test/LLVM/Test/ExecutionEngine.hs +59/−0
- test/LLVM/Test/Global.hs +42/−0
- test/LLVM/Test/InlineAssembly.hs +81/−0
- test/LLVM/Test/Instructions.hs +1235/−0
- test/LLVM/Test/Instrumentation.hs +159/−0
- test/LLVM/Test/Linking.hs +66/−0
- test/LLVM/Test/Metadata.hs +157/−0
- test/LLVM/Test/Module.hs +574/−0
- test/LLVM/Test/ObjectCode.hs +35/−0
- test/LLVM/Test/Optimization.hs +306/−0
- test/LLVM/Test/OrcJIT.hs +103/−0
- test/LLVM/Test/Support.hs +42/−0
- test/LLVM/Test/Target.hs +71/−0
- test/LLVM/Test/Tests.hs +39/−0
- test/Test.hs +10/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2013, Benjamin S. Scarlet and Google Inc.+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Benjamin S. Scarlet nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,189 @@+{-# LANGUAGE FlexibleInstances #-}+import Control.Exception (SomeException, try)+import Control.Monad+import Data.Functor+import Data.Maybe+import Data.List (isPrefixOf, (\\), intercalate, stripPrefix, find)+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Monoid+import Data.Char+import Distribution.Simple+import Distribution.Simple.PreProcess+import Distribution.Simple.Program+import Distribution.Simple.Setup hiding (Flag)+import Distribution.Simple.LocalBuildInfo+import Distribution.PackageDescription+import Distribution.Version+import System.Environment+import Distribution.System++-- define these selectively in C files (we are _not_ using HsFFI.h),+-- rather than universally in the ccOptions, because HsFFI.h currently defines them+-- without checking they're already defined and so causes warnings.+uncheckedHsFFIDefines = ["__STDC_LIMIT_MACROS"]++llvmVersion = Version [4,0] []++llvmConfigNames = [+ "llvm-config-" ++ (intercalate "." . map show . versionBranch $ llvmVersion),+ "llvm-config"+ ]++findJustBy :: Monad m => (a -> m (Maybe b)) -> [a] -> m (Maybe b)+findJustBy f (x:xs) = do+ x' <- f x+ case x' of+ Nothing -> findJustBy f xs+ j -> return j+findJustBy _ [] = return Nothing++class ProgramSearch a where+ programSearch :: (String -> a) -> a++-- this instance is used before Cabal-1.18.0, when programFindLocation took one argument+instance Monad m => ProgramSearch (v -> m (Maybe b)) where+ programSearch checkName = \v -> findJustBy (\n -> checkName n v) llvmConfigNames++-- this instance is used for and after Cabal-1.18.0, when programFindLocation took two arguments+instance Monad m => ProgramSearch (v -> p -> m (Maybe b)) where+ programSearch checkName = \v p -> findJustBy (\n -> checkName n v p) llvmConfigNames++class OldHookable hook where+ preHookOld :: (PackageDescription -> LocalBuildInfo -> UserHooks -> TestFlags -> IO ()) -> hook -> hook++-- this instance is used before Cabal-1.22.0.0, when testHook took four arguments+instance OldHookable (PackageDescription -> LocalBuildInfo -> UserHooks -> TestFlags -> IO ()) where+ preHookOld f hook = \packageDescription localBuildInfo userHooks testFlags -> do+ f packageDescription localBuildInfo userHooks testFlags+ hook packageDescription localBuildInfo userHooks testFlags++-- this instance is used for and after Cabal-1.22.0.0, when testHook took four five arguments+instance OldHookable (Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> TestFlags -> IO ()) where+ preHookOld f hook = \args packageDescription localBuildInfo userHooks testFlags -> do+ f packageDescription localBuildInfo userHooks testFlags+ hook args packageDescription localBuildInfo userHooks testFlags++llvmProgram :: Program+llvmProgram = (simpleProgram "llvm-config") {+ programFindLocation = programSearch (programFindLocation . simpleProgram),+ programFindVersion =+ let+ stripSuffix suf str = let r = reverse in liftM r (stripPrefix (r suf) (r str))+ svnToTag v = maybe v (++"-svn") (stripSuffix "svn" v)+ trim = dropWhile isSpace . reverse . dropWhile isSpace . reverse+ in+ \v p -> findProgramVersion "--version" (svnToTag . trim) v p+ }++getLLVMConfig :: ConfigFlags -> IO ([String] -> IO String)+getLLVMConfig configFlags = do+ let verbosity = fromFlag $ configVerbosity configFlags+ (program, _, _) <- requireProgramVersion verbosity llvmProgram+ (withinVersion llvmVersion)+ (configPrograms configFlags)+ return $ getProgramOutput verbosity program++addToLdLibraryPath :: String -> IO ()+addToLdLibraryPath path = do+ let (ldLibraryPathVar, ldLibraryPathSep) =+ case buildOS of+ OSX -> ("DYLD_LIBRARY_PATH",":")+ _ -> ("LD_LIBRARY_PATH",":")+ v <- try $ getEnv ldLibraryPathVar :: IO (Either SomeException String)+ setEnv ldLibraryPathVar (path ++ either (const "") (ldLibraryPathSep ++) v)++addLLVMToLdLibraryPath :: ConfigFlags -> IO ()+addLLVMToLdLibraryPath configFlags = do+ llvmConfig <- getLLVMConfig configFlags+ [libDir] <- liftM lines $ llvmConfig ["--libdir"]+ addToLdLibraryPath libDir++-- | These flags are not relevant for us and dropping them allows+-- linking against LLVM build with Clang using GCC+ignoredCxxFlags :: [String]+ignoredCxxFlags =+ ["-Wcovered-switch-default", "-fcolor-diagnostics"] ++ map ("-D" ++) uncheckedHsFFIDefines++ignoredCFlags :: [String]+ignoredCFlags = ["-Wcovered-switch-default", "-Wdelete-non-virtual-dtor", "-fcolor-diagnostics"]++-- | Header directories are added separately to configExtraIncludeDirs+isIncludeFlag :: String -> Bool+isIncludeFlag flag = "-I" `isPrefixOf` flag++isIgnoredCFlag :: String -> Bool+isIgnoredCFlag flag = flag `elem` ignoredCFlags || isIncludeFlag flag++isIgnoredCxxFlag :: String -> Bool+isIgnoredCxxFlag flag = flag `elem` ignoredCxxFlags || isIncludeFlag flag++main = do+ let origUserHooks = simpleUserHooks++ defaultMainWithHooks origUserHooks {+ hookedPrograms = [ llvmProgram ],++ confHook = \(genericPackageDescription, hookedBuildInfo) configFlags -> do+ llvmConfig <- getLLVMConfig configFlags+ llvmCxxFlags <- do+ rawLlvmCxxFlags <- llvmConfig ["--cxxflags"]+ return . filter (not . isIgnoredCxxFlag) $ words rawLlvmCxxFlags+ let stdLib = maybe "stdc++"+ (drop (length stdlibPrefix))+ (find (isPrefixOf stdlibPrefix) llvmCxxFlags)+ where stdlibPrefix = "-stdlib=lib"+ includeDirs <- liftM lines $ llvmConfig ["--includedir"]+ libDirs@[libDir] <- liftM lines $ llvmConfig ["--libdir"]+ [llvmVersion] <- liftM lines $ llvmConfig ["--version"]+ let getLibs = liftM (map (fromJust . stripPrefix "-l") . words) . llvmConfig+ flags = configConfigurationsFlags configFlags+ linkFlag = case lookup (FlagName "shared-llvm") flags of+ Nothing -> "--link-static"+ Just shared -> if shared then "--link-shared" else "--link-static"+ libs <- getLibs ["--libs", linkFlag]+ systemLibs <- getLibs ["--system-libs"]++ let genericPackageDescription' = genericPackageDescription {+ condLibrary = do+ libraryCondTree <- condLibrary genericPackageDescription+ return libraryCondTree {+ condTreeData = condTreeData libraryCondTree <> mempty {+ libBuildInfo =+ mempty {+ ccOptions = llvmCxxFlags,+ extraLibs = stdLib : libs ++ systemLibs+ }+ }+ }+ }+ configFlags' = configFlags {+ configExtraLibDirs = libDirs ++ configExtraLibDirs configFlags,+ configExtraIncludeDirs = includeDirs ++ configExtraIncludeDirs configFlags+ }+ addLLVMToLdLibraryPath configFlags'+ confHook simpleUserHooks (genericPackageDescription', hookedBuildInfo) configFlags',++ hookedPreProcessors =+ let origHookedPreprocessors = hookedPreProcessors origUserHooks+ newHsc buildInfo localBuildInfo =+ PreProcessor {+ platformIndependent = platformIndependent (origHsc buildInfo localBuildInfo),+ runPreProcessor = \inFiles outFiles verbosity -> do+ llvmConfig <- getLLVMConfig (configFlags localBuildInfo)+ llvmCFlags <- do+ rawLlvmCFlags <- llvmConfig ["--cflags"]+ return . filter (not . isIgnoredCFlag) $ words rawLlvmCFlags+ let buildInfo' = buildInfo { ccOptions = "-Wno-variadic-macros" : llvmCFlags }+ runPreProcessor (origHsc buildInfo' localBuildInfo) inFiles outFiles verbosity+ }+ where origHsc = fromMaybe ppHsc2hs (lookup "hsc" origHookedPreprocessors)+ in [("hsc", newHsc)] ++ origHookedPreprocessors,++ buildHook = \packageDescription localBuildInfo userHooks buildFlags -> do+ addLLVMToLdLibraryPath (configFlags localBuildInfo)+ buildHook origUserHooks packageDescription localBuildInfo userHooks buildFlags,++ testHook = preHookOld (\_ localBuildInfo _ _ -> addLLVMToLdLibraryPath (configFlags localBuildInfo))+ (testHook origUserHooks)+ }
+ llvm-hs.cabal view
@@ -0,0 +1,273 @@+name: llvm-hs+version: 4.0.0.0+license: BSD3+license-file: LICENSE+author: Anthony Cowley, Stephen Diehl, Moritz Kiefer <moritz.kiefer@purelyfunctional.org>, Benjamin S. Scarlet+maintainer: Anthony Cowley, Stephen Diehl, Moritz Kiefer <moritz.kiefer@purelyfunctional.org>+copyright: (c) 2013 Benjamin S. Scarlet and Google Inc.+homepage: http://github.com/llvm-hs/llvm-hs/+bug-reports: http://github.com/llvm-hs/llvm-hs/issues+build-type: Custom+stability: experimental+cabal-version: >= 1.8+category: Compilers/Interpreters, Code Generation+synopsis: General purpose LLVM bindings+description:+ llvm-hs is a set of Haskell bindings for LLVM <http://llvm.org/>. Unlike other current Haskell bindings,+ it uses an ADT to represent LLVM IR (<http://llvm.org/docs/LangRef.html>), and so offers two advantages: it+ handles almost all of the stateful complexities of using the LLVM API to build IR; and it supports moving IR not+ only from Haskell into LLVM C++ objects, but the other direction - from LLVM C++ into Haskell.+extra-source-files:+ src/LLVM/Internal/FFI/Analysis.h+ src/LLVM/Internal/FFI/Attribute.h+ src/LLVM/Internal/FFI/AttributeC.hpp+ src/LLVM/Internal/FFI/BinaryOperator.h+ src/LLVM/Internal/FFI/CallingConvention.h+ src/LLVM/Internal/FFI/Constant.h+ src/LLVM/Internal/FFI/GlobalValue.h+ src/LLVM/Internal/FFI/InlineAssembly.h+ src/LLVM/Internal/FFI/Instruction.h+ src/LLVM/Internal/FFI/LibFunc.h+ src/LLVM/Internal/FFI/Metadata.hpp+ src/LLVM/Internal/FFI/OrcJIT.h+ src/LLVM/Internal/FFI/SMDiagnostic.h+ src/LLVM/Internal/FFI/Target.h+ src/LLVM/Internal/FFI/Target.hpp+ src/LLVM/Internal/FFI/Type.h+ src/LLVM/Internal/FFI/Value.h+tested-with: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2++source-repository head+ type: git+ location: git://github.com/llvm-hs/llvm-hs.git+ branch: llvm-4++flag shared-llvm+ description: link against llvm shared rather than static library+ default: True++flag debug+ description: compile C(++) shims with debug info for ease of troubleshooting+ default: False++flag semigroups+ description: Add semigroups to build-depends for Data.List.NonEmpty. This will be selected automatically by cabal.+ default: False++custom-setup+ setup-depends: base+ , Cabal+ , containers++library+ build-tools: llvm-config+ ghc-options: -Wall -fno-warn-name-shadowing -fno-warn-orphans -fno-warn-incomplete-patterns -fno-warn-missing-signatures -fno-warn-unused-matches -fno-warn-unused-do-bind -fno-warn-type-defaults+ if flag(semigroups)+ build-depends:+ base >= 4.7 && < 4.9,+ semigroups >= 0.18 && < 0.19+ else+ build-depends:+ base >= 4.9 && < 5+ build-depends:+ utf8-string >= 0.3.7,+ bytestring >= 0.9.1.10,+ transformers >= 0.3 && < 0.6,+ transformers-compat >= 0.4,+ mtl >= 2.1.3,+ template-haskell >= 2.5.0.0,+ containers >= 0.4.2.1,+ parsec >= 3.1.3,+ array >= 0.4.0.0,+ llvm-hs-pure == 4.0.0.0+ hs-source-dirs: src+ extensions:+ NoImplicitPrelude+ TupleSections+ DeriveDataTypeable+ EmptyDataDecls+ FlexibleContexts+ FlexibleInstances+ StandaloneDeriving+ ConstraintKinds+ exposed-modules:+ LLVM+ LLVM.Analysis+ LLVM.CodeGenOpt+ LLVM.CodeModel+ LLVM.CommandLine+ LLVM.Context+ LLVM.Diagnostic+ LLVM.ExecutionEngine+ LLVM.Internal.Analysis+ LLVM.Internal.Atomicity+ LLVM.Internal.Attribute+ LLVM.Internal.BasicBlock+ LLVM.Internal.CallingConvention+ LLVM.Internal.Coding+ LLVM.Internal.CommandLine+ LLVM.Internal.Constant+ LLVM.Internal.Context+ LLVM.Internal.DataLayout+ LLVM.Internal.DecodeAST+ LLVM.Internal.Diagnostic+ LLVM.Internal.EncodeAST+ LLVM.Internal.ExecutionEngine+ LLVM.Internal.FastMathFlags+ LLVM.Internal.FloatingPointPredicate+ LLVM.Internal.Function+ LLVM.Internal.Global+ LLVM.Internal.Inject+ LLVM.Internal.InlineAssembly+ LLVM.Internal.Instruction+ LLVM.Internal.InstructionDefs+ LLVM.Internal.IntegerPredicate+ LLVM.Internal.LibraryFunction+ LLVM.Internal.MemoryBuffer+ LLVM.Internal.Metadata+ LLVM.Internal.Module+ LLVM.Internal.OrcJIT+ LLVM.Internal.OrcJIT.CompileOnDemandLayer+ LLVM.Internal.OrcJIT.IRCompileLayer+ LLVM.Internal.Operand+ LLVM.Internal.PassManager+ LLVM.Internal.RawOStream+ LLVM.Internal.RMWOperation+ LLVM.Internal.String+ LLVM.Internal.TailCallKind+ LLVM.Internal.Target+ LLVM.Internal.Threading+ LLVM.Internal.Type+ LLVM.Internal.Value+ LLVM.Internal.FFI.Analysis+ LLVM.Internal.FFI.Attribute+ LLVM.Internal.FFI.Assembly+ LLVM.Internal.FFI.BasicBlock+ LLVM.Internal.FFI.BinaryOperator+ LLVM.Internal.FFI.Bitcode+ LLVM.Internal.FFI.Builder+ LLVM.Internal.FFI.ByteRangeCallback+ LLVM.Internal.FFI.Cleanup+ LLVM.Internal.FFI.CommandLine+ LLVM.Internal.FFI.Constant+ LLVM.Internal.FFI.Context+ LLVM.Internal.FFI.DataLayout+ LLVM.Internal.FFI.ExecutionEngine+ LLVM.Internal.FFI.Function+ LLVM.Internal.FFI.GlobalAlias+ LLVM.Internal.FFI.GlobalValue+ LLVM.Internal.FFI.GlobalVariable+ LLVM.Internal.FFI.InlineAssembly+ LLVM.Internal.FFI.Instruction+ LLVM.Internal.FFI.InstructionDefs+ LLVM.Internal.FFI.Iterate+ LLVM.Internal.FFI.LLVMCTypes+ LLVM.Internal.FFI.MemoryBuffer+ LLVM.Internal.FFI.Metadata+ LLVM.Internal.FFI.Module+ LLVM.Internal.FFI.OrcJIT+ LLVM.Internal.FFI.OrcJIT.CompileOnDemandLayer+ LLVM.Internal.FFI.OrcJIT.IRCompileLayer+ LLVM.Internal.FFI.PassManager+ LLVM.Internal.FFI.PtrHierarchy+ LLVM.Internal.FFI.RawOStream+ LLVM.Internal.FFI.SMDiagnostic+ LLVM.Internal.FFI.Target+ LLVM.Internal.FFI.Threading+ LLVM.Internal.FFI.Transforms+ LLVM.Internal.FFI.Type+ LLVM.Internal.FFI.User+ LLVM.Internal.FFI.Value+ LLVM.Module+ LLVM.OrcJIT+ LLVM.OrcJIT.CompileOnDemandLayer+ LLVM.OrcJIT.IRCompileLayer+ LLVM.PassManager+ LLVM.Relocation+ LLVM.Target+ LLVM.Target.LibraryFunction+ LLVM.Target.Options+ LLVM.Threading+ LLVM.Transforms++ other-modules:+ Control.Monad.AnyCont+ Control.Monad.AnyCont.Class+ Control.Monad.Trans.AnyCont++ include-dirs: src+ c-sources:+ src/LLVM/Internal/FFI/AssemblyC.cpp+ src/LLVM/Internal/FFI/AttributeC.cpp+ src/LLVM/Internal/FFI/BitcodeC.cpp+ src/LLVM/Internal/FFI/BuilderC.cpp+ src/LLVM/Internal/FFI/CallingConventionC.cpp+ src/LLVM/Internal/FFI/ConstantC.cpp+ src/LLVM/Internal/FFI/CommandLineC.cpp+ src/LLVM/Internal/FFI/ExecutionEngineC.cpp+ src/LLVM/Internal/FFI/FunctionC.cpp+ src/LLVM/Internal/FFI/GlobalAliasC.cpp+ src/LLVM/Internal/FFI/GlobalValueC.cpp+ src/LLVM/Internal/FFI/InlineAssemblyC.cpp+ src/LLVM/Internal/FFI/InstructionC.cpp+ src/LLVM/Internal/FFI/MetadataC.cpp+ src/LLVM/Internal/FFI/ModuleC.cpp+ src/LLVM/Internal/FFI/OrcJITC.cpp+ src/LLVM/Internal/FFI/RawOStreamC.cpp+ src/LLVM/Internal/FFI/PassManagerC.cpp+ src/LLVM/Internal/FFI/SMDiagnosticC.cpp+ src/LLVM/Internal/FFI/TargetC.cpp+ src/LLVM/Internal/FFI/TypeC.cpp+ src/LLVM/Internal/FFI/ValueC.cpp++ if flag(debug)+ cc-options: -g++test-suite test+ type: exitcode-stdio-1.0+ if flag(semigroups)+ build-depends:+ base >= 4.7 && < 4.9,+ semigroups >= 0.18 && < 0.19+ else+ build-depends:+ base >= 4.9 && < 5+ build-depends:+ bytestring >= 0.10 && < 0.11,+ tasty >= 0.11,+ tasty-hunit >= 0.9,+ tasty-quickcheck >= 0.8,+ QuickCheck >= 2.5.1.1,+ llvm-hs,+ llvm-hs-pure == 4.0.0.0,+ containers >= 0.4.2.1,+ mtl >= 2.1,+ transformers >= 0.3.0.0,+ transformers-compat,+ temporary >= 1.2 && < 1.3,+ pretty-show >= 1.6 && < 1.7+ hs-source-dirs: test+ extensions:+ TupleSections+ FlexibleInstances+ FlexibleContexts+ main-is: Test.hs+ other-modules:+ LLVM.Test.Analysis+ LLVM.Test.CallingConvention+ LLVM.Test.Constants+ LLVM.Test.DataLayout+ LLVM.Test.ExecutionEngine+ LLVM.Test.Global+ LLVM.Test.InlineAssembly+ LLVM.Test.Instructions+ LLVM.Test.Instrumentation+ LLVM.Test.Linking+ LLVM.Test.Metadata+ LLVM.Test.Module+ LLVM.Test.ObjectCode+ LLVM.Test.OrcJIT+ LLVM.Test.Optimization+ LLVM.Test.Support+ LLVM.Test.Target+ LLVM.Test.Tests
+ src/Control/Monad/AnyCont.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+module Control.Monad.AnyCont (+ MonadAnyCont(..),+ ScopeAnyCont(..),+ AnyContT(..),+ MonadTransAnyCont(..),+ runAnyContT,+ withAnyContT,+ mapAnyContT+ ) where++import Prelude++import Control.Monad.Trans.AnyCont+import Control.Monad.AnyCont.Class+import Control.Monad.Trans.Class+import Control.Monad.State.Class+import Control.Monad.Error.Class++instance MonadState s m => MonadState s (AnyContT m) where+ get = lift get+ put = lift . put+ state = lift . state++instance MonadError e m => MonadError e (AnyContT m) where+ throwError = lift . throwError+ x `catchError` h = anyContT $ \f -> (runAnyContT x f) `catchError` (\e -> runAnyContT (h e) f)
+ src/Control/Monad/AnyCont/Class.hs view
@@ -0,0 +1,54 @@+{-# LANGUAGE+ RankNTypes,+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+module Control.Monad.AnyCont.Class where++import Prelude++import Control.Monad.Trans.Class+import Control.Monad.Trans.AnyCont (AnyContT)+import qualified Control.Monad.Trans.AnyCont as AnyCont+import Control.Monad.Trans.Except as Except+import Control.Monad.Trans.State as State++class ScopeAnyCont m where+ scopeAnyCont :: m a -> m a++class MonadAnyCont b m where+ anyContToM :: (forall r . (a -> b r) -> b r) -> m a+++instance MonadTransAnyCont b m => MonadAnyCont b (AnyContT m) where+ anyContToM c = AnyCont.anyContT (liftAnyCont c)++instance Monad m => ScopeAnyCont (AnyContT m) where+ scopeAnyCont = lift . flip AnyCont.runAnyContT return+++instance (Monad m, MonadAnyCont b m) => MonadAnyCont b (StateT s m) where+ anyContToM x = lift $ anyContToM x++instance ScopeAnyCont m => ScopeAnyCont (StateT s m) where+ scopeAnyCont = StateT . (scopeAnyCont .) . runStateT+++instance (Monad m, MonadAnyCont b m) => MonadAnyCont b (ExceptT e m) where+ anyContToM x = lift $ anyContToM x+++instance ScopeAnyCont m => ScopeAnyCont (ExceptT e m) where+ scopeAnyCont = mapExceptT scopeAnyCont++class MonadTransAnyCont b m where+ liftAnyCont :: (forall r . (a -> b r) -> b r) -> (forall r . (a -> m r) -> m r)++instance MonadTransAnyCont b b where+ liftAnyCont c = c++instance MonadTransAnyCont b m => MonadTransAnyCont b (StateT s m) where+ liftAnyCont c = (\c q -> StateT $ \s -> c $ ($ s) . runStateT . q) (liftAnyCont c)++instance MonadTransAnyCont b m => MonadTransAnyCont b (ExceptT e m) where+ liftAnyCont c = (\c q -> ExceptT . c $ runExceptT . q) (liftAnyCont c)
+ src/Control/Monad/Trans/AnyCont.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE+ RankNTypes+ #-}+module Control.Monad.Trans.AnyCont where++import LLVM.Prelude++import Control.Monad.Cont++newtype AnyContT m a = AnyContT { unAnyContT :: forall r . ContT r m a }++instance Functor (AnyContT m) where+ fmap f p = AnyContT $ fmap f . unAnyContT $ p++instance Applicative (AnyContT m) where+ pure a = AnyContT $ pure a+ f <*> v = AnyContT $ unAnyContT f <*> unAnyContT v++instance Monad m => Monad (AnyContT m) where+ AnyContT f >>= k = AnyContT $ f >>= unAnyContT . k+ return a = AnyContT $ return a+ fail s = AnyContT (ContT (\_ -> fail s))+ +instance MonadIO m => MonadIO (AnyContT m) where+ liftIO = lift . liftIO++instance MonadTrans AnyContT where+ lift ma = AnyContT (lift ma)++runAnyContT :: AnyContT m a -> (forall r . (a -> m r) -> m r)+runAnyContT = runContT . unAnyContT+anyContT :: (forall r . (a -> m r) -> m r) -> AnyContT m a+anyContT f = AnyContT (ContT f)++withAnyContT :: (forall r . (b -> m r) -> (a -> m r)) -> AnyContT m a -> AnyContT m b+withAnyContT f m = anyContT $ runAnyContT m . f++mapAnyContT :: (forall r . m r -> m r) -> AnyContT m a -> AnyContT m a+mapAnyContT f m = anyContT $ f . runAnyContT m+
+ src/LLVM.hs view
@@ -0,0 +1,7 @@+-- | An interface to use LLVM in all capacities+module LLVM (+ module LLVM.Module+ ) where++import LLVM.Module+
+ src/LLVM/Analysis.hs view
@@ -0,0 +1,8 @@+-- | functionality for analyzing 'LLVM.Module.Module's. Much of the analysis+-- possible with LLVM is managed internally, as needed by 'Transforms', and so is not+-- yet exposed here.+module LLVM.Analysis (+ verify+ ) where++import LLVM.Internal.Analysis
+ src/LLVM/CodeGenOpt.hs view
@@ -0,0 +1,12 @@+-- | Code generation options, used in specifying TargetMachine+module LLVM.CodeGenOpt where++import LLVM.Prelude++-- | <http://llvm.org/doxygen/namespacellvm_1_1CodeGenOpt.html>+data Level+ = None+ | Less+ | Default+ | Aggressive+ deriving (Eq, Ord, Read, Show, Typeable, Data)
+ src/LLVM/CodeModel.hs view
@@ -0,0 +1,14 @@+-- | Relocations, used in specifying TargetMachine+module LLVM.CodeModel where++import LLVM.Prelude++-- | <http://llvm.org/doxygen/namespacellvm_1_1CodeModel.html>+data Model+ = Default+ | JITDefault+ | Small+ | Kernel+ | Medium+ | Large+ deriving (Eq, Read, Show, Typeable, Data)
+ src/LLVM/CommandLine.hs view
@@ -0,0 +1,8 @@+-- | Tools for processing command line arguments, for command line tools build+-- with llvm (or for other uses forced into pretending to be such to get at (ack)+-- global state).+module LLVM.CommandLine (+ parseCommandLineOptions+) where++import LLVM.Internal.CommandLine
+ src/LLVM/Context.hs view
@@ -0,0 +1,7 @@+-- | functions for the LLVM Context object which holds thread-scope state+module LLVM.Context (+ Context,+ withContext+ ) where++import LLVM.Internal.Context
+ src/LLVM/Diagnostic.hs view
@@ -0,0 +1,33 @@+-- | Diagnostics describe parse errors+module LLVM.Diagnostic (+ DiagnosticKind(..),+ Diagnostic(..),+ diagnosticDisplay+ ) where++import LLVM.Prelude++-- | What kind of problem does a diagnostic describe?+data DiagnosticKind + = ErrorKind+ | WarningKind+ | NoteKind+ deriving (Eq, Ord, Read, Show, Typeable, Data)++-- | A 'Diagnostic' described a problem during parsing of LLVM IR+data Diagnostic = Diagnostic {+ lineNumber :: Int,+ columnNumber :: Int,+ diagnosticKind :: DiagnosticKind,+ filename :: String,+ message :: String,+ lineContents :: String+ }+ deriving (Eq, Ord, Read, Show)++-- | Convert a 'Diagnostic' to a printable form.+diagnosticDisplay :: Diagnostic -> String+diagnosticDisplay d = + (filename d) ++ ":" ++ show (lineNumber d) ++ ":" ++ show (columnNumber d)+ ++ ":\n" ++ show (diagnosticKind d) ++ ": " ++ (message d) ++ "\n"+ ++ (lineContents d) ++ "\n"
+ src/LLVM/ExecutionEngine.hs view
@@ -0,0 +1,8 @@+-- | Tools for JIT execution+module LLVM.ExecutionEngine (+ ExecutionEngine(..),+ ExecutableModule,+ MCJIT, withMCJIT+ ) where++import LLVM.Internal.ExecutionEngine
+ src/LLVM/Internal/Analysis.hs view
@@ -0,0 +1,24 @@+module LLVM.Internal.Analysis where++import LLVM.Prelude++import Control.Monad.AnyCont+import Control.Monad.Error.Class+import Control.Monad.IO.Class+import Control.Monad.Trans.Except++import qualified LLVM.Internal.FFI.Analysis as FFI+import qualified LLVM.Internal.FFI.LLVMCTypes as FFI++import LLVM.Internal.Module+import LLVM.Internal.Coding++-- | Run basic sanity checks on a 'Module'. Note that the same checks will trigger assertions+-- within LLVM if LLVM was built with them turned on, before this function can be is called.+verify :: Module -> ExceptT String IO ()+verify m = flip runAnyContT return $ do+ errorPtr <- alloca+ m' <- readModule m+ result <- decodeM =<< (liftIO $ FFI.verifyModule m' FFI.verifierFailureActionReturnStatus errorPtr)+ when result $ throwError =<< decodeM errorPtr+
+ src/LLVM/Internal/Atomicity.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE+ TemplateHaskell,+ MultiParamTypeClasses+ #-}+module LLVM.Internal.Atomicity where++import LLVM.Prelude++import Data.Maybe++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI++import LLVM.Internal.Coding+import qualified LLVM.AST as A++genCodingInstance [t| Maybe A.MemoryOrdering |] ''FFI.MemoryOrdering [+ (FFI.memoryOrderingNotAtomic, Nothing),+ (FFI.memoryOrderingUnordered, Just A.Unordered),+ (FFI.memoryOrderingMonotonic, Just A.Monotonic),+ (FFI.memoryOrderingAcquire, Just A.Acquire),+ (FFI.memoryOrderingRelease, Just A.Release),+ (FFI.memoryOrderingAcquireRelease, Just A.AcquireRelease),+ (FFI.memoryOrderingSequentiallyConsistent, Just A.SequentiallyConsistent)+ ]++genCodingInstance [t| A.SynchronizationScope |] ''FFI.SynchronizationScope [+ (FFI.synchronizationScopeSingleThread, A.SingleThread),+ (FFI.synchronizationScopeCrossThread, A.CrossThread)+ ]++instance Monad m => EncodeM m (Maybe A.Atomicity) (FFI.SynchronizationScope, FFI.MemoryOrdering) where+ encodeM a =+ return (,) `ap` encodeM (maybe A.SingleThread fst a) `ap` encodeM (liftM snd a)++instance Monad m => DecodeM m (Maybe A.Atomicity) (FFI.SynchronizationScope, FFI.MemoryOrdering) where+ decodeM (ss, ao) = return (liftM . (,)) `ap` decodeM ss `ap` decodeM ao++instance Monad m => EncodeM m A.Atomicity (FFI.SynchronizationScope, FFI.MemoryOrdering) where+ encodeM = encodeM . Just++instance Monad m => DecodeM m A.Atomicity (FFI.SynchronizationScope, FFI.MemoryOrdering) where+ decodeM = liftM fromJust . decodeM++instance Monad m => EncodeM m A.MemoryOrdering FFI.MemoryOrdering where+ encodeM = encodeM . Just++instance Monad m => DecodeM m A.MemoryOrdering FFI.MemoryOrdering where+ decodeM = liftM fromJust . decodeM+
+ src/LLVM/Internal/Attribute.hs view
@@ -0,0 +1,279 @@+{-# LANGUAGE+ MultiParamTypeClasses,+ ConstraintKinds,+ QuasiQuotes,+ UndecidableInstances,+ RankNTypes+ #-}+module LLVM.Internal.Attribute where++import LLVM.Prelude++import Control.Monad.AnyCont+import Control.Monad.IO.Class+import Control.Monad.State (gets)++import Foreign.C (CUInt)+import Foreign.Ptr+import Data.Either+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Maybe++import qualified LLVM.Internal.FFI.Attribute as FFI+import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import LLVM.Internal.FFI.LLVMCTypes (parameterAttributeKindP, functionAttributeKindP) ++import qualified LLVM.AST.ParameterAttribute as A.PA +import qualified LLVM.AST.FunctionAttribute as A.FA ++import LLVM.Internal.Coding+import LLVM.Internal.Context +import LLVM.Internal.EncodeAST+import LLVM.Internal.DecodeAST++inconsistentCases :: Show a => String -> a -> b+inconsistentCases name attr =+ error $ "llvm-hs internal error: cases inconstistent in " ++ name ++ " encoding for " ++ show attr++instance Monad m => EncodeM m A.PA.ParameterAttribute (Ptr FFI.ParameterAttrBuilder -> EncodeAST ()) where+ encodeM a = return $ \b -> liftIO $ case a of+ A.PA.Alignment v -> FFI.attrBuilderAddAlignment b v+ A.PA.Dereferenceable v -> FFI.attrBuilderAddDereferenceable b v+ A.PA.DereferenceableOrNull v -> FFI.attrBuilderAddDereferenceableOrNull b v+ _ -> FFI.attrBuilderAddParameterAttributeKind b $ case a of+ A.PA.ZeroExt -> FFI.parameterAttributeKindZExt+ A.PA.SignExt -> FFI.parameterAttributeKindSExt+ A.PA.InReg -> FFI.parameterAttributeKindInReg+ A.PA.SRet -> FFI.parameterAttributeKindStructRet+ A.PA.NoAlias -> FFI.parameterAttributeKindNoAlias+ A.PA.ByVal -> FFI.parameterAttributeKindByVal+ A.PA.NoCapture -> FFI.parameterAttributeKindNoCapture+ A.PA.Nest -> FFI.parameterAttributeKindNest+ A.PA.ReadOnly -> FFI.parameterAttributeKindReadOnly+ A.PA.ReadNone -> FFI.parameterAttributeKindReadNone+ A.PA.InAlloca -> FFI.parameterAttributeKindInAlloca+ A.PA.NonNull -> FFI.parameterAttributeKindNonNull+ A.PA.Returned -> FFI.parameterAttributeKindReturned+ A.PA.SwiftSelf -> FFI.parameterAttributeKindSwiftSelf+ A.PA.SwiftError -> FFI.parameterAttributeKindSwiftError+ A.PA.WriteOnly -> FFI.parameterAttributeKindWriteOnly+ A.PA.Alignment _ -> inconsistentCases "ParameterAttribute" a+ A.PA.Dereferenceable _ -> inconsistentCases "ParameterAttribute" a+ A.PA.DereferenceableOrNull _ -> inconsistentCases "ParameterAttribute" a++instance Monad m => EncodeM m A.FA.FunctionAttribute (Ptr FFI.FunctionAttrBuilder -> EncodeAST ()) where+ encodeM (A.FA.StringAttribute kind value) = return $ \b -> do+ (kindP, kindLen) <- encodeM kind+ (valueP, valueLen) <- encodeM value+ liftIO $ FFI.attrBuilderAddStringAttribute b kindP kindLen valueP valueLen+ encodeM a = return $ \b -> case a of+ A.FA.StackAlignment v -> liftIO $ FFI.attrBuilderAddStackAlignment b v+ A.FA.AllocSize x y -> do+ x' <- encodeM x+ y' <- encodeM y+ liftIO $ FFI.attrBuilderAddAllocSize b x' y'+ _ -> liftIO $ FFI.attrBuilderAddFunctionAttributeKind b $ case a of+ A.FA.Convergent -> FFI.functionAttributeKindConvergent+ A.FA.InaccessibleMemOnly -> FFI.functionAttributeKindInaccessibleMemOnly+ A.FA.InaccessibleMemOrArgMemOnly -> FFI.functionAttributeKindInaccessibleMemOrArgMemOnly+ A.FA.NoReturn -> FFI.functionAttributeKindNoReturn+ A.FA.NoUnwind -> FFI.functionAttributeKindNoUnwind+ A.FA.ReadNone -> FFI.functionAttributeKindReadNone+ A.FA.ReadOnly -> FFI.functionAttributeKindReadOnly+ A.FA.NoInline -> FFI.functionAttributeKindNoInline+ A.FA.NoRecurse -> FFI.functionAttributeKindNoRecurse+ A.FA.AlwaysInline -> FFI.functionAttributeKindAlwaysInline+ A.FA.MinimizeSize -> FFI.functionAttributeKindMinSize+ A.FA.OptimizeForSize -> FFI.functionAttributeKindOptimizeForSize+ A.FA.OptimizeNone -> FFI.functionAttributeKindOptimizeForSize+ A.FA.WriteOnly -> FFI.functionAttributeKindWriteOnly+ A.FA.ArgMemOnly -> FFI.functionAttributeKindArgMemOnly+ A.FA.StackProtect -> FFI.functionAttributeKindStackProtect+ A.FA.StackProtectReq -> FFI.functionAttributeKindStackProtectReq+ A.FA.StackProtectStrong -> FFI.functionAttributeKindStackProtectStrong+ A.FA.NoRedZone -> FFI.functionAttributeKindNoRedZone+ A.FA.NoImplicitFloat -> FFI.functionAttributeKindNoImplicitFloat+ A.FA.Naked -> FFI.functionAttributeKindNaked+ A.FA.InlineHint -> FFI.functionAttributeKindInlineHint+ A.FA.ReturnsTwice -> FFI.functionAttributeKindReturnsTwice+ A.FA.UWTable -> FFI.functionAttributeKindUWTable+ A.FA.NonLazyBind -> FFI.functionAttributeKindNonLazyBind+ A.FA.Builtin -> FFI.functionAttributeKindBuiltin+ A.FA.NoBuiltin -> FFI.functionAttributeKindNoBuiltin+ A.FA.Cold -> FFI.functionAttributeKindCold+ A.FA.JumpTable -> FFI.functionAttributeKindJumpTable+ A.FA.NoDuplicate -> FFI.functionAttributeKindNoDuplicate+ A.FA.SanitizeAddress -> FFI.functionAttributeKindSanitizeAddress+ A.FA.SanitizeThread -> FFI.functionAttributeKindSanitizeThread+ A.FA.SanitizeMemory -> FFI.functionAttributeKindSanitizeMemory+ A.FA.SafeStack -> FFI.functionAttributeKindSafeStack+ A.FA.StackAlignment _ -> inconsistentCases "FunctionAttribute" a+ A.FA.AllocSize _ _ -> inconsistentCases "FunctionAttribute" a+ A.FA.StringAttribute _ _ -> inconsistentCases "FunctionAttribute" a++instance DecodeM DecodeAST A.PA.ParameterAttribute FFI.ParameterAttribute where+ decodeM a = do+ enum <- liftIO $ FFI.parameterAttributeKindAsEnum a+ case enum of+ [parameterAttributeKindP|ZExt|] -> return A.PA.ZeroExt+ [parameterAttributeKindP|SExt|] -> return A.PA.SignExt+ [parameterAttributeKindP|InReg|] -> return A.PA.InReg+ [parameterAttributeKindP|StructRet|] -> return A.PA.SRet+ [parameterAttributeKindP|Alignment|] -> return A.PA.Alignment `ap` (liftIO $ FFI.attributeValueAsInt a)+ [parameterAttributeKindP|NoAlias|] -> return A.PA.NoAlias+ [parameterAttributeKindP|ByVal|] -> return A.PA.ByVal+ [parameterAttributeKindP|NoCapture|] -> return A.PA.NoCapture+ [parameterAttributeKindP|Nest|] -> return A.PA.Nest+ [parameterAttributeKindP|ReadOnly|] -> return A.PA.ReadOnly+ [parameterAttributeKindP|ReadNone|] -> return A.PA.ReadNone+ [parameterAttributeKindP|WriteOnly|] -> return A.PA.WriteOnly+ [parameterAttributeKindP|InAlloca|] -> return A.PA.InAlloca+ [parameterAttributeKindP|NonNull|] -> return A.PA.NonNull+ [parameterAttributeKindP|Dereferenceable|] -> return A.PA.Dereferenceable `ap` (liftIO $ FFI.attributeValueAsInt a)+ [parameterAttributeKindP|DereferenceableOrNull|] -> return A.PA.DereferenceableOrNull `ap` (liftIO $ FFI.attributeValueAsInt a)+ [parameterAttributeKindP|Returned|] -> return A.PA.Returned+ [parameterAttributeKindP|SwiftSelf|] -> return A.PA.SwiftSelf+ [parameterAttributeKindP|SwiftError|] -> return A.PA.SwiftError+ _ -> error $ "unhandled parameter attribute enum value: " ++ show enum++instance DecodeM DecodeAST A.FA.FunctionAttribute FFI.FunctionAttribute where+ decodeM a = do+ isString <- decodeM =<< (liftIO $ FFI.isStringAttribute a)+ if isString+ then+ return A.FA.StringAttribute+ `ap` (decodeM $ FFI.attributeKindAsString a)+ `ap` (decodeM $ FFI.attributeValueAsString a) + else do+ enum <- liftIO $ FFI.functionAttributeKindAsEnum a+ case enum of+ [functionAttributeKindP|AllocSize|] -> do+ x <- alloca+ y <- alloca+ isJust <- liftIO $ FFI.attributeGetAllocSizeArgs a x y+ x' <- decodeM =<< peek x+ y' <- peek y+ yM <- decodeM (y', isJust)+ return (A.FA.AllocSize x' yM)+ [functionAttributeKindP|NoReturn|] -> return A.FA.NoReturn+ [functionAttributeKindP|NoUnwind|] -> return A.FA.NoUnwind+ [functionAttributeKindP|ReadNone|] -> return A.FA.ReadNone+ [functionAttributeKindP|ReadOnly|] -> return A.FA.ReadOnly+ [functionAttributeKindP|NoInline|] -> return A.FA.NoInline+ [functionAttributeKindP|NoRecurse|] -> return A.FA.NoRecurse+ [functionAttributeKindP|AlwaysInline|] -> return A.FA.AlwaysInline+ [functionAttributeKindP|MinSize|] -> return A.FA.MinimizeSize+ [functionAttributeKindP|OptimizeForSize|] -> return A.FA.OptimizeForSize+ [functionAttributeKindP|OptimizeNone|] -> return A.FA.OptimizeForSize+ [functionAttributeKindP|StackProtect|] -> return A.FA.StackProtect+ [functionAttributeKindP|StackProtectReq|] -> return A.FA.StackProtectReq+ [functionAttributeKindP|StackProtectStrong|] -> return A.FA.StackProtectStrong+ [functionAttributeKindP|NoRedZone|] -> return A.FA.NoRedZone+ [functionAttributeKindP|NoImplicitFloat|] -> return A.FA.NoImplicitFloat+ [functionAttributeKindP|Naked|] -> return A.FA.Naked+ [functionAttributeKindP|InlineHint|] -> return A.FA.InlineHint+ [functionAttributeKindP|StackAlignment|] -> return A.FA.StackAlignment `ap` (liftIO $ FFI.attributeValueAsInt a)+ [functionAttributeKindP|ReturnsTwice|] -> return A.FA.ReturnsTwice+ [functionAttributeKindP|UWTable|] -> return A.FA.UWTable+ [functionAttributeKindP|NonLazyBind|] -> return A.FA.NonLazyBind+ [functionAttributeKindP|Builtin|] -> return A.FA.Builtin+ [functionAttributeKindP|NoBuiltin|] -> return A.FA.NoBuiltin+ [functionAttributeKindP|Cold|] -> return A.FA.Cold+ [functionAttributeKindP|JumpTable|] -> return A.FA.JumpTable+ [functionAttributeKindP|NoDuplicate|] -> return A.FA.NoDuplicate+ [functionAttributeKindP|SanitizeAddress|] -> return A.FA.SanitizeAddress+ [functionAttributeKindP|SanitizeThread|] -> return A.FA.SanitizeThread+ [functionAttributeKindP|SanitizeMemory|] -> return A.FA.SanitizeMemory+ [functionAttributeKindP|ArgMemOnly|] -> return A.FA.ArgMemOnly+ [functionAttributeKindP|Convergent|] -> return A.FA.Convergent+ [functionAttributeKindP|InaccessibleMemOnly|] -> return A.FA.InaccessibleMemOnly+ [functionAttributeKindP|InaccessibleMemOrArgMemOnly|] -> return A.FA.InaccessibleMemOrArgMemOnly+ [functionAttributeKindP|SafeStack|] -> return A.FA.SafeStack+ [functionAttributeKindP|WriteOnly|] -> return A.FA.WriteOnly+ _ -> error $ "unhandled function attribute enum value: " ++ show enum++allocaAttrBuilder :: (Monad m, MonadAnyCont IO m) => m (Ptr (FFI.AttrBuilder a))+allocaAttrBuilder = do+ p <- allocaArray FFI.getAttrBuilderSize+ anyContToM $ \f -> do+ ab <- FFI.constructAttrBuilder p+ r <- f ab+ FFI.destroyAttrBuilder ab+ return r++instance EncodeM EncodeAST a (Ptr (FFI.AttrBuilder b) -> EncodeAST ()) => EncodeM EncodeAST (FFI.Index, [a]) (FFI.AttributeSet b) where+ encodeM (index, as) = scopeAnyCont $ do+ ab <- allocaAttrBuilder+ builds <- mapM encodeM as+ forM builds ($ ab) :: EncodeAST [()]+ Context context <- gets encodeStateContext+ liftIO $ FFI.getAttributeSet context index ab++instance EncodeM EncodeAST [A.FA.FunctionAttribute] FFI.FunctionAttributeSet where+ encodeM fas = encodeM (FFI.functionIndex, fas)++instance DecodeM DecodeAST a (FFI.Attribute b) => DecodeM DecodeAST [a] (FFI.AttributeSet b) where+ decodeM as = do+ np <- alloca+ as <- liftIO $ FFI.attributeSetGetAttributes as 0 np+ n <- peek np+ decodeM (n, as)+ +data MixedAttributeSet = MixedAttributeSet {+ functionAttributes :: [Either A.FA.GroupID A.FA.FunctionAttribute],+ returnAttributes :: [A.PA.ParameterAttribute],+ parameterAttributes :: Map CUInt [A.PA.ParameterAttribute]+ }+ deriving (Eq, Show)++data PreSlot+ = IndirectFunctionAttributes A.FA.GroupID+ | DirectFunctionAttributes [A.FA.FunctionAttribute]+ | ReturnAttributes [A.PA.ParameterAttribute]+ | ParameterAttributes CUInt [A.PA.ParameterAttribute] ++instance EncodeM EncodeAST PreSlot FFI.MixedAttributeSet where+ encodeM preSlot = do+ let forget = liftM FFI.forgetAttributeType+ case preSlot of+ IndirectFunctionAttributes gid -> forget (referAttributeGroup gid)+ DirectFunctionAttributes fas -> forget (encodeM fas :: EncodeAST FFI.FunctionAttributeSet)+ ReturnAttributes as -> forget (encodeM (FFI.returnIndex, as) :: EncodeAST FFI.ParameterAttributeSet)+ ParameterAttributes i as -> forget (encodeM (fromIntegral (i + 1) :: FFI.Index, as) :: EncodeAST FFI.ParameterAttributeSet)++instance EncodeM EncodeAST MixedAttributeSet FFI.MixedAttributeSet where+ encodeM (MixedAttributeSet fAttrs rAttrs pAttrs) = do+ let directP = DirectFunctionAttributes (rights fAttrs)+ indirectPs = map IndirectFunctionAttributes (lefts fAttrs)+ returnP = ReturnAttributes rAttrs+ paramPs = [ ParameterAttributes x as | (x, as) <- Map.toList pAttrs ]+ (nAttrs, attrs) <- encodeM ([directP, returnP] ++ indirectPs ++ paramPs)+ Context context <- gets encodeStateContext+ liftIO $ FFI.mixAttributeSets context attrs nAttrs++instance DecodeM DecodeAST MixedAttributeSet FFI.MixedAttributeSet where+ decodeM mas = do+ numSlots <- if mas == nullPtr then return 0 else liftIO $ FFI.attributeSetNumSlots mas+ slotIndexes <- forM (take (fromIntegral numSlots) [0..]) $ \s -> do+ i <- liftIO $ FFI.attributeSetSlotIndex mas s+ return (i, s)+ let separate :: Ord k => k -> Map k a -> (Maybe a, Map k a)+ separate = Map.updateLookupWithKey (\_ _ -> Nothing)+ indexedSlots = Map.fromList slotIndexes+ unless (Map.size indexedSlots == length slotIndexes) $+ fail "unexpected slot index collision decoding mixed AttributeSet"+ let (functionSlot, otherSlots) = separate FFI.functionIndex (Map.fromList slotIndexes)+ functionAnnotation <- for (maybeToList functionSlot) $ \slot -> do+ a <- liftIO $ FFI.attributeSetSlotAttributes mas slot+ getAttributeGroupID a+ otherAttributeSets <- for otherSlots $ \slot -> do+ a <- liftIO $ FFI.attributeSetSlotAttributes mas slot+ decodeM (a :: FFI.ParameterAttributeSet)+ let (returnAttributeSet, shiftedParameterAttributeSets) = separate FFI.returnIndex otherAttributeSets+ return $ MixedAttributeSet {+ functionAttributes = fmap Left functionAnnotation,+ returnAttributes = join . maybeToList $ returnAttributeSet,+ parameterAttributes = Map.mapKeysMonotonic (\x -> fromIntegral x - 1) shiftedParameterAttributeSets+ }+
+ src/LLVM/Internal/BasicBlock.hs view
@@ -0,0 +1,27 @@+module LLVM.Internal.BasicBlock where++import LLVM.Prelude++import Control.Monad.Trans+import Foreign.Ptr++import qualified LLVM.Internal.FFI.PtrHierarchy as FFI+import qualified LLVM.Internal.FFI.BasicBlock as FFI+import qualified LLVM.Internal.FFI.Iterate as FFI++import LLVM.Internal.DecodeAST+import LLVM.Internal.Coding+import LLVM.Internal.Instruction ()++import qualified LLVM.AST.Instruction as A++getBasicBlockTerminator :: Ptr FFI.BasicBlock -> DecodeAST (DecodeAST (A.Named A.Terminator))+getBasicBlockTerminator = decodeM <=< (liftIO . FFI.getBasicBlockTerminator)++getNamedInstructions :: Ptr FFI.BasicBlock -> DecodeAST (DecodeAST [A.Named A.Instruction])+getNamedInstructions b = do+ ffiInstructions <- liftIO $ FFI.getXs (FFI.getFirstInstruction b) FFI.getNextInstruction+ let n = length ffiInstructions+ liftM sequence . forM (take (n-1) ffiInstructions) $ decodeM++
+ src/LLVM/Internal/CallingConvention.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE+ MultiParamTypeClasses,+ TemplateHaskell,+ QuasiQuotes+ #-}+module LLVM.Internal.CallingConvention where++import LLVM.Prelude++import LLVM.Internal.Coding+import Foreign.C.Types (CUInt(..))++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import LLVM.Internal.FFI.LLVMCTypes (callingConventionP)++import qualified LLVM.AST.CallingConvention as A.CC++instance Monad m => EncodeM m A.CC.CallingConvention FFI.CallingConvention where+ encodeM cc = return $ + case cc of+ A.CC.C -> FFI.callingConventionC+ A.CC.Fast -> FFI.callingConventionFast+ A.CC.Cold -> FFI.callingConventionCold+ A.CC.GHC -> FFI.callingConventionGHC+ A.CC.HiPE -> FFI.callingConventionHiPE+ A.CC.WebKit_JS -> FFI.callingConventionWebKit_JS+ A.CC.AnyReg -> FFI.callingConventionAnyReg+ A.CC.PreserveMost -> FFI.callingConventionPreserveMost+ A.CC.PreserveAll -> FFI.callingConventionPreserveAll+ A.CC.X86_StdCall -> FFI.callingConventionX86_StdCall+ A.CC.X86_FastCall -> FFI.callingConventionX86_FastCall+ A.CC.ARM_APCS -> FFI.callingConventionARM_APCS+ A.CC.ARM_AAPCS -> FFI.callingConventionARM_AAPCS+ A.CC.ARM_AAPCS_VFP -> FFI.callingConventionARM_AAPCS_VFP+ A.CC.MSP430_INTR -> FFI.callingConventionMSP430_INTR+ A.CC.X86_ThisCall -> FFI.callingConventionX86_ThisCall+ A.CC.PTX_Kernel -> FFI.callingConventionPTX_Kernel+ A.CC.PTX_Device -> FFI.callingConventionPTX_Device+ A.CC.SPIR_FUNC -> FFI.callingConventionSPIR_FUNC+ A.CC.SPIR_KERNEL -> FFI.callingConventionSPIR_KERNEL+ A.CC.Intel_OCL_BI -> FFI.callingConventionIntel_OCL_BI+ A.CC.X86_64_SysV -> FFI.callingConventionX86_64_SysV+ A.CC.X86_64_Win64 -> FFI.callingConventionX86_64_Win64+ A.CC.Numbered cc' -> FFI.CallingConvention (fromIntegral cc')++instance Monad m => DecodeM m A.CC.CallingConvention FFI.CallingConvention where+ decodeM cc = return $ case cc of+ [callingConventionP|C|] -> A.CC.C+ [callingConventionP|Fast|] -> A.CC.Fast+ [callingConventionP|Cold|] -> A.CC.Cold+ [callingConventionP|GHC|] -> A.CC.GHC+ [callingConventionP|HiPE|] -> A.CC.HiPE+ [callingConventionP|WebKit_JS|] -> A.CC.WebKit_JS+ [callingConventionP|AnyReg|] -> A.CC.AnyReg+ [callingConventionP|PreserveMost|] -> A.CC.PreserveMost+ [callingConventionP|PreserveAll|] -> A.CC.PreserveAll+ [callingConventionP|X86_StdCall|] -> A.CC.X86_StdCall+ [callingConventionP|X86_FastCall|] -> A.CC.X86_FastCall+ [callingConventionP|ARM_APCS|] -> A.CC.ARM_APCS+ [callingConventionP|ARM_AAPCS|] -> A.CC.ARM_AAPCS+ [callingConventionP|ARM_AAPCS_VFP|] -> A.CC.ARM_AAPCS_VFP+ [callingConventionP|MSP430_INTR|] -> A.CC.MSP430_INTR+ [callingConventionP|X86_ThisCall|] -> A.CC.X86_ThisCall+ [callingConventionP|PTX_Kernel|] -> A.CC.PTX_Kernel+ [callingConventionP|PTX_Device|] -> A.CC.PTX_Device+ [callingConventionP|SPIR_FUNC|] -> A.CC.SPIR_FUNC+ [callingConventionP|SPIR_KERNEL|] -> A.CC.SPIR_KERNEL+ [callingConventionP|Intel_OCL_BI|] -> A.CC.Intel_OCL_BI+ [callingConventionP|X86_64_SysV|] -> A.CC.X86_64_SysV+ [callingConventionP|X86_64_Win64|] -> A.CC.X86_64_Win64+ FFI.CallingConvention (CUInt ci) | ci >= 64 -> A.CC.Numbered (fromIntegral ci)
+ src/LLVM/Internal/Coding.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE+ TemplateHaskell,+ MultiParamTypeClasses,+ FunctionalDependencies,+ UndecidableInstances+ #-}+module LLVM.Internal.Coding where++import LLVM.Prelude++import Language.Haskell.TH+import Language.Haskell.TH.Quote++import Control.Monad.AnyCont+import Control.Monad.IO.Class++import Foreign.C+import Foreign.Ptr+import Foreign.Storable+import Foreign.Marshal.Alloc+import Foreign.Marshal.Array++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI++class EncodeM e h c where+ encodeM :: h -> e c++class DecodeM d h c where+ decodeM :: c -> d h++genCodingInstance :: (Data c, Data h) => TypeQ -> Name -> [(c, h)] -> Q [Dec]+genCodingInstance ht ctn chs = do+ let n = const Nothing+ [d| + instance Monad m => EncodeM m $(ht) $(conT ctn) where+ encodeM h = return $ $(+ caseE [| h |] [ match (dataToPatQ n h) (normalB (dataToExpQ n c)) [] | (c,h) <- chs ] + )++ instance Monad m => DecodeM m $(ht) $(conT ctn) where+ decodeM c = return $ $(+ caseE [| c |] [ match (dataToPatQ n c) (normalB (dataToExpQ n h)) [] | (c,h) <- chs ]+ )+ |]++allocaArray :: (Integral i, Storable a, MonadAnyCont IO m) => i -> m (Ptr a)+allocaArray p = anyContToM $ Foreign.Marshal.Array.allocaArray (fromIntegral p)++alloca :: (Storable a, MonadAnyCont IO m) => m (Ptr a)+alloca = anyContToM Foreign.Marshal.Alloc.alloca++peek :: (Storable a, MonadIO m) => Ptr a -> m a+peek p = liftIO $ Foreign.Storable.peek p++peekByteOff :: (Storable a, MonadIO m) => Ptr a -> Int -> m a+peekByteOff p i = liftIO $ Foreign.Storable.peekByteOff p i++poke :: (Storable a, MonadIO m) => Ptr a -> a -> m ()+poke p a = liftIO $ Foreign.Storable.poke p a++pokeByteOff :: (Storable a, MonadIO m) => Ptr a -> Int -> a -> m ()+pokeByteOff p i a = liftIO $ Foreign.Storable.pokeByteOff p i a++peekArray :: (Integral i, Storable a, MonadIO m) => i -> Ptr a -> m [a]+peekArray n p = liftIO $ Foreign.Marshal.Array.peekArray (fromIntegral n) p++instance (Monad m, EncodeM m h c, Storable c, MonadAnyCont IO m) => EncodeM m [h] (CUInt, Ptr c) where+ encodeM hs = do+ hs <- mapM encodeM hs+ (anyContToM $ \x -> Foreign.Marshal.Array.withArrayLen hs $ \n hs -> x (fromIntegral n, hs))++instance (Monad m, DecodeM m h c, Storable c, MonadIO m) => DecodeM m [h] (CUInt, Ptr c) where+ decodeM (n, ca) = do+ cs <- liftIO $ Foreign.Marshal.Array.peekArray (fromIntegral n) ca+ mapM decodeM cs++instance Monad m => EncodeM m Bool FFI.LLVMBool where+ encodeM False = return $ FFI.LLVMBool 0+ encodeM True = return $ FFI.LLVMBool 1++instance Monad m => DecodeM m Bool FFI.LLVMBool where+ decodeM (FFI.LLVMBool 0) = return $ False+ decodeM (FFI.LLVMBool _) = return $ True++instance (Monad m, EncodeM m h (Ptr c)) => EncodeM m (Maybe h) (Ptr c) where+ encodeM = maybe (return nullPtr) encodeM++instance (Monad m, DecodeM m h (Ptr c)) => DecodeM m (Maybe h) (Ptr c) where+ decodeM p | p == nullPtr = return Nothing+ | otherwise = liftM Just $ decodeM p++instance Monad m => EncodeM m (Maybe Bool) (FFI.NothingAsMinusOne Bool) where+ encodeM = return . FFI.NothingAsMinusOne . maybe (-1) (fromIntegral . fromEnum)++instance Monad m => EncodeM m (Maybe Word) (FFI.NothingAsMinusOne Word) where+ encodeM = return . FFI.NothingAsMinusOne . maybe (-1) fromIntegral++instance Monad m => EncodeM m (Maybe Word) (CUInt, FFI.LLVMBool) where+ encodeM (Just a) = liftM2 (,) (encodeM a) (encodeM True)+ encodeM Nothing = return (0,) `ap` (encodeM False)++instance Monad m => DecodeM m (Maybe Word) (CUInt, FFI.LLVMBool) where+ decodeM (a, isJust) = do+ isJust' <- decodeM isJust+ if isJust'+ then liftM Just (decodeM a)+ else return Nothing++instance Monad m => EncodeM m Word CUInt where+ encodeM = return . fromIntegral++instance Monad m => EncodeM m Word32 CUInt where+ encodeM = return . fromIntegral++instance Monad m => EncodeM m Word64 CULong where+ encodeM = return . fromIntegral++instance Monad m => DecodeM m Word CUInt where+ decodeM = return . fromIntegral++instance Monad m => DecodeM m Word32 CUInt where+ decodeM = return . fromIntegral++instance Monad m => DecodeM m Word64 CULong where+ decodeM = return . fromIntegral++instance Monad m => EncodeM m Int32 CInt where+ encodeM = return . fromIntegral++instance Monad m => DecodeM m Int32 CInt where+ decodeM = return . fromIntegral++instance Monad m => DecodeM m Int CInt where+ decodeM = return . fromIntegral++instance Monad m => EncodeM m Word64 Word64 where+ encodeM = return++instance Monad m => DecodeM m Word64 Word64 where+ decodeM = return
+ src/LLVM/Internal/CommandLine.hs view
@@ -0,0 +1,23 @@+module LLVM.Internal.CommandLine where++import LLVM.Prelude++import Control.Monad.AnyCont+import Control.Monad.IO.Class++import Foreign.Ptr++import qualified LLVM.Internal.FFI.CommandLine as FFI++import LLVM.Internal.Coding+import LLVM.Internal.String ()++-- | <http://llvm.org/doxygen/namespacellvm_1_1cl.html#a992a39dae9eb8d4e54ffee5467902803>+-- Sadly, there is occasionally some configuration one would like to control+-- in LLVM which are accessible only as command line flags setting global state,+-- as if the command line tools were the only use of LLVM. Very sad.+parseCommandLineOptions :: [String] -> Maybe String -> IO ()+parseCommandLineOptions args overview = flip runAnyContT return $ do+ args <- encodeM args+ overview <- maybe (return nullPtr) encodeM overview+ liftIO $ FFI.parseCommandLineOptions args overview
+ src/LLVM/Internal/Constant.hs view
@@ -0,0 +1,248 @@+{-# LANGUAGE+ TemplateHaskell,+ QuasiQuotes,+ MultiParamTypeClasses,+ ScopedTypeVariables+ #-}+module LLVM.Internal.Constant where++import LLVM.Prelude++import qualified Language.Haskell.TH as TH+import qualified Language.Haskell.TH.Quote as TH+import qualified LLVM.Internal.InstructionDefs as ID++import Data.Bits+import Control.Monad.State (get, gets, modify, evalState)+import Control.Monad.AnyCont+import Control.Monad.IO.Class++import qualified Data.Map as Map+import Foreign.Ptr+import Foreign.Storable (Storable, sizeOf)++import qualified LLVM.Internal.FFI.Constant as FFI+import qualified LLVM.Internal.FFI.GlobalValue as FFI+import qualified LLVM.Internal.FFI.Instruction as FFI+import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import LLVM.Internal.FFI.LLVMCTypes (valueSubclassIdP)+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI+import qualified LLVM.Internal.FFI.Type as FFI+import qualified LLVM.Internal.FFI.User as FFI+import qualified LLVM.Internal.FFI.Value as FFI+import qualified LLVM.Internal.FFI.BinaryOperator as FFI++import qualified LLVM.AST.Constant as A (Constant)+import qualified LLVM.AST.Constant as A.C hiding (Constant)+import qualified LLVM.AST.Type as A+import qualified LLVM.AST.IntegerPredicate as A (IntegerPredicate)+import qualified LLVM.AST.FloatingPointPredicate as A (FloatingPointPredicate)+import qualified LLVM.AST.Float as A.F++import LLVM.Internal.Coding+import LLVM.Internal.DecodeAST+import LLVM.Internal.EncodeAST+import LLVM.Internal.Context+import LLVM.Internal.Type ()+import LLVM.Internal.IntegerPredicate ()+import LLVM.Internal.FloatingPointPredicate ()++allocaWords :: forall a m . (Storable a, MonadAnyCont IO m, Monad m, MonadIO m) => Word32 -> m (Ptr a)+allocaWords nBits = do+ allocaArray (((nBits-1) `div` (8*(fromIntegral (sizeOf (undefined :: a))))) + 1)++instance EncodeM EncodeAST A.Constant (Ptr FFI.Constant) where+ encodeM c = scopeAnyCont $ case c of+ A.C.Int { A.C.integerBits = bits, A.C.integerValue = v } -> do+ t <- encodeM (A.IntegerType bits)+ words <- encodeM [+ fromIntegral ((v `shiftR` (w*64)) .&. 0xffffffffffffffff) :: Word64+ | w <- [0 .. ((fromIntegral bits-1) `div` 64)] + ]+ liftIO $ FFI.constantIntOfArbitraryPrecision t words+ A.C.Float { A.C.floatValue = v } -> do+ Context context <- gets encodeStateContext+ let poke1 f = do+ let nBits = fromIntegral $ 8*(sizeOf f)+ words <- allocaWords nBits+ poke (castPtr words) f+ return (nBits, words)+ poke2 fh fl = do+ let nBits = fromIntegral $ 8*(sizeOf fh) + 8*(sizeOf fl)+ words <- allocaWords nBits+ pokeByteOff (castPtr words) 0 fl+ pokeByteOff (castPtr words) (sizeOf fl) fh+ return (nBits, words)+ (nBits, words) <- case v of+ A.F.Half f -> poke1 f+ A.F.Single f -> poke1 f+ A.F.Double f -> poke1 f+ A.F.X86_FP80 high low -> poke2 high low+ A.F.Quadruple high low -> poke2 high low+ A.F.PPC_FP128 high low -> poke2 high low+ let fpSem = case v of+ A.F.Half _ -> FFI.floatSemanticsIEEEhalf+ A.F.Single _ -> FFI.floatSemanticsIEEEsingle+ A.F.Double _ -> FFI.floatSemanticsIEEEdouble+ A.F.Quadruple _ _ -> FFI.floatSemanticsIEEEquad+ A.F.X86_FP80 _ _ -> FFI.floatSemanticsx87DoubleExtended+ A.F.PPC_FP128 _ _ -> FFI.floatSemanticsPPCDoubleDouble+ nBits <- encodeM nBits+ liftIO $ FFI.constantFloatOfArbitraryPrecision context nBits words fpSem+ A.C.GlobalReference _ n -> FFI.upCast <$> referGlobal n+ A.C.BlockAddress f b -> do+ f' <- referGlobal f+ b' <- getBlockForAddress f b+ liftIO $ FFI.blockAddress (FFI.upCast f') b'+ A.C.Struct nm p ms -> do+ p <- encodeM p+ ms <- encodeM ms+ case nm of+ Nothing -> do+ Context context <- gets encodeStateContext+ liftIO $ FFI.constStructInContext context ms p+ Just nm -> do+ t <- lookupNamedType nm+ liftIO $ FFI.constNamedStruct t ms+ A.C.TokenNone -> do+ Context context <- gets encodeStateContext+ liftIO $ FFI.getConstTokenNone context+ o -> $(do+ let constExprInfo = ID.outerJoin ID.astConstantRecs (ID.innerJoin ID.astInstructionRecs ID.instructionDefs)+ TH.caseE [| o |] $ do+ (name, (Just (TH.RecC n fs), instrInfo)) <- Map.toList constExprInfo+ let fns = [ TH.mkName . TH.nameBase $ fn | (fn, _, _) <- fs ]+ coreCall n = TH.dyn $ "FFI.constant" ++ n+ buildBody c = [ TH.bindS (TH.varP fn) [| encodeM $(TH.varE fn) |] | fn <- fns ]+ ++ [ TH.noBindS [| liftIO $(foldl TH.appE c (map TH.varE fns)) |] ]+ hasFlags = any (== ''Bool) [ h | (_, _, TH.ConT h) <- fs ]+ core <- case instrInfo of+ Just (_, iDef) -> do+ let opcode = TH.dataToExpQ (const Nothing) (ID.cppOpcode iDef)+ case ID.instructionKind iDef of+ ID.Binary | hasFlags -> return $ coreCall name+ | True -> return [| $(coreCall "BinaryOperator") $(opcode) |]+ ID.Cast -> return [| $(coreCall "Cast") $(opcode) |]+ _ -> return $ coreCall name+ Nothing -> if (name `elem` ["Vector", "Null", "Array", "Undef"])+ then return $ coreCall name+ else []+ return $ TH.match+ (TH.recP n [(fn,) <$> (TH.varP . TH.mkName . TH.nameBase $ fn) | (fn, _, _) <- fs])+ (TH.normalB (TH.doE (buildBody core)))+ []+ )++instance DecodeM DecodeAST A.Constant (Ptr FFI.Constant) where+ decodeM c = scopeAnyCont $ do+ let v = FFI.upCast c :: Ptr FFI.Value+ u = FFI.upCast c :: Ptr FFI.User+ ft <- liftIO (FFI.typeOf v)+ t <- decodeM ft+ valueSubclassId <- liftIO $ FFI.getValueSubclassId v+ nOps <- liftIO $ FFI.getNumOperands u+ let globalRef = return A.C.GlobalReference + `ap` (return t)+ `ap` (getGlobalName =<< liftIO (FFI.isAGlobalValue v))+ op = decodeM <=< liftIO . FFI.getConstantOperand c+ getConstantOperands = mapM op [0..nOps-1] + getConstantData = do+ let nElements = case t of+ A.VectorType n _ -> n+ A.ArrayType n _ | n <= (fromIntegral (maxBound :: Word32)) -> fromIntegral n+ forM [0..nElements-1] $ do+ decodeM <=< liftIO . FFI.getConstantDataSequentialElementAsConstant c . fromIntegral++ case valueSubclassId of+ [valueSubclassIdP|Function|] -> globalRef+ [valueSubclassIdP|GlobalAlias|] -> globalRef+ [valueSubclassIdP|GlobalVariable|] -> globalRef+ [valueSubclassIdP|ConstantInt|] -> do+ np <- alloca+ wsp <- liftIO $ FFI.getConstantIntWords c np+ n <- peek np+ words <- decodeM (n, wsp)+ return $ A.C.Int (A.typeBits t) (foldr (\b a -> (a `shiftL` 64) .|. fromIntegral b) 0 (words :: [Word64]))+ [valueSubclassIdP|ConstantFP|] -> do+ let A.FloatingPointType nBits fmt = t+ ws <- allocaWords nBits+ liftIO $ FFI.getConstantFloatWords c ws+ A.C.Float <$> (+ case (nBits, fmt) of+ (16, A.IEEE) -> A.F.Half <$> peek (castPtr ws)+ (32, A.IEEE) -> A.F.Single <$> peek (castPtr ws)+ (64, A.IEEE) -> A.F.Double <$> peek (castPtr ws)+ (128, A.IEEE) -> A.F.Quadruple <$> peekByteOff (castPtr ws) 8 <*> peekByteOff (castPtr ws) 0+ (80, A.DoubleExtended) -> A.F.X86_FP80 <$> peekByteOff (castPtr ws) 8 <*> peekByteOff (castPtr ws) 0+ (128, A.PairOfFloats) -> A.F.PPC_FP128 <$> peekByteOff (castPtr ws) 8 <*> peekByteOff (castPtr ws) 0+ _ -> error $ "don't know how to decode floating point constant of type: " ++ show t+ )+ [valueSubclassIdP|ConstantPointerNull|] -> return $ A.C.Null t+ [valueSubclassIdP|ConstantAggregateZero|] -> return $ A.C.Null t+ [valueSubclassIdP|UndefValue|] -> return $ A.C.Undef t+ [valueSubclassIdP|BlockAddress|] -> + return A.C.BlockAddress + `ap` (getGlobalName =<< do liftIO $ FFI.isAGlobalValue =<< FFI.getBlockAddressFunction c)+ `ap` (getLocalName =<< do liftIO $ FFI.getBlockAddressBlock c)+ [valueSubclassIdP|ConstantStruct|] -> do+ return A.C.Struct+ `ap` (return $ case t of A.NamedTypeReference n -> Just n; _ -> Nothing)+ `ap` (decodeM =<< liftIO (FFI.isPackedStruct ft))+ `ap` getConstantOperands+ [valueSubclassIdP|ConstantDataArray|] -> + return A.C.Array `ap` (return $ A.elementType t) `ap` getConstantData+ [valueSubclassIdP|ConstantArray|] -> + return A.C.Array `ap` (return $ A.elementType t) `ap` getConstantOperands+ [valueSubclassIdP|ConstantDataVector|] -> + return A.C.Vector `ap` getConstantData+ [valueSubclassIdP|ConstantExpr|] -> do+ cppOpcode <- liftIO $ FFI.getConstantCPPOpcode c+ $(+ TH.caseE [| cppOpcode |] $ do+ (name, ((TH.RecC n fs, _), iDef)) <- Map.toList $+ ID.innerJoin (ID.innerJoin ID.astConstantRecs ID.astInstructionRecs) ID.instructionDefs+ let apWrapper o (fn, _, ct) = do+ a <- case ct of+ TH.ConT h+ | h == ''A.Constant -> do+ operandNumber <- get+ modify (+1)+ return [| op $(TH.litE . TH.integerL $ operandNumber) |]+ | h == ''A.Type -> return [| pure t |]+ | h == ''A.IntegerPredicate -> + return [| liftIO $ decodeM =<< FFI.getConstantICmpPredicate c |]+ | h == ''A.FloatingPointPredicate -> + return [| liftIO $ decodeM =<< FFI.getConstantFCmpPredicate c |]+ | h == ''Bool -> case TH.nameBase fn of+ "inBounds" -> return [| liftIO $ decodeM =<< FFI.getInBounds v |]+ "exact" -> return [| liftIO $ decodeM =<< FFI.isExact v |]+ "nsw" -> return [| liftIO $ decodeM =<< FFI.hasNoSignedWrap v |]+ "nuw" -> return [| liftIO $ decodeM =<< FFI.hasNoUnsignedWrap v |]+ x -> error $ "constant bool field " ++ show x ++ " not handled yet"+ TH.AppT TH.ListT (TH.ConT h) + | h == ''Word32 -> + return [|+ do+ np <- alloca+ isp <- liftIO $ FFI.getConstantIndices c np+ n <- peek np+ decodeM (n, isp)+ |]+ | h == ''A.Constant -> + case TH.nameBase fn of+ "indices" -> do+ operandNumber <- get+ return [| mapM op [$(TH.litE . TH.integerL $ operandNumber)..nOps-1] |]+ _ -> error $ "unhandled constant expr field type: " ++ show fn ++ " - " ++ show ct+ return [| $(o) `ap` $(a) |]+ return $ TH.match + (TH.dataToPatQ (const Nothing) (ID.cppOpcode iDef))+ (TH.normalB (evalState (foldM apWrapper [| return $(TH.conE n) |] fs) 0))+ []+ )+ [valueSubclassIdP|ConstantTokenNone|] -> return A.C.TokenNone+ _ -> error $ "unhandled constant valueSubclassId: " ++ show valueSubclassId+++ +
+ src/LLVM/Internal/Context.hs view
@@ -0,0 +1,20 @@+module LLVM.Internal.Context where++import LLVM.Prelude++import Control.Exception+import Control.Concurrent++import Foreign.Ptr++import qualified LLVM.Internal.FFI.Context as FFI++-- | a Context object holds the state the of LLVM system needs for one thread of+-- | LLVM compilation. Once upon a time, in early versions of LLVM, this state was global.+-- | Then it got packed up in this object to allow multiple threads to compile at once.+data Context = Context (Ptr FFI.Context)++-- | Create a Context, run an action (to which it is provided), then destroy the Context.+withContext :: (Context -> IO a) -> IO a+withContext = runBound . bracket FFI.contextCreate FFI.contextDispose . (. Context)+ where runBound = if rtsSupportsBoundThreads then runInBoundThread else id
+ src/LLVM/Internal/DataLayout.hs view
@@ -0,0 +1,23 @@+module LLVM.Internal.DataLayout where++import LLVM.Prelude++import Control.Exception+import Control.Monad.AnyCont+import Control.Monad.IO.Class++import Foreign.Ptr++import qualified LLVM.Internal.FFI.DataLayout as FFI++import LLVM.AST.DataLayout+import LLVM.DataLayout++import LLVM.Internal.Coding+import LLVM.Internal.String ()++withFFIDataLayout :: DataLayout -> (Ptr FFI.DataLayout -> IO a) -> IO a+withFFIDataLayout dl f = flip runAnyContT return $ do+ dls <- encodeM (dataLayoutToString dl)+ liftIO $ bracket (FFI.createDataLayout dls) FFI.disposeDataLayout f+
+ src/LLVM/Internal/DecodeAST.hs view
@@ -0,0 +1,172 @@+{-# LANGUAGE+ GeneralizedNewtypeDeriving,+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+module LLVM.Internal.DecodeAST where++import LLVM.Prelude++import Control.Monad.State+import Control.Monad.AnyCont++import Foreign.Ptr+import Foreign.C++import Data.Sequence (Seq)+import qualified Data.Sequence as Seq+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Array (Array)+import qualified Data.Array as Array++import qualified LLVM.Internal.FFI.Attribute as FFI+import qualified LLVM.Internal.FFI.GlobalValue as FFI+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI+import qualified LLVM.Internal.FFI.Value as FFI+import qualified LLVM.Internal.FFI.Type as FFI++import qualified LLVM.AST.Name as A+import qualified LLVM.AST.Operand as A (MetadataNodeID(..))+import qualified LLVM.AST.Attribute as A.A+import qualified LLVM.AST.COMDAT as A.COMDAT++import LLVM.Internal.Coding+import LLVM.Internal.String ()++type NameMap a = Map (Ptr a) Word++data DecodeState = DecodeState {+ globalVarNum :: NameMap FFI.GlobalValue,+ localVarNum :: NameMap FFI.Value,+ localNameCounter :: Maybe Word,+ namedTypeNum :: NameMap FFI.Type,+ typesToDefine :: Seq (Ptr FFI.Type),+ metadataNodesToDefine :: Seq (A.MetadataNodeID, Ptr FFI.MDNode),+ metadataNodes :: Map (Ptr FFI.MDNode) A.MetadataNodeID,+ metadataKinds :: Array Word String,+ parameterAttributeSets :: Map FFI.ParameterAttributeSet [A.A.ParameterAttribute],+ functionAttributeSetIDs :: Map FFI.FunctionAttributeSet A.A.GroupID,+ comdats :: Map (Ptr FFI.COMDAT) (String, A.COMDAT.SelectionKind)+ }+initialDecode = DecodeState {+ globalVarNum = Map.empty,+ localVarNum = Map.empty,+ localNameCounter = Nothing,+ namedTypeNum = Map.empty,+ typesToDefine = Seq.empty,+ metadataNodesToDefine = Seq.empty,+ metadataNodes = Map.empty,+ metadataKinds = Array.listArray (1,0) [],+ parameterAttributeSets = Map.empty,+ functionAttributeSetIDs = Map.empty,+ comdats = Map.empty+ }+newtype DecodeAST a = DecodeAST { unDecodeAST :: AnyContT (StateT DecodeState IO) a }+ deriving (+ Applicative,+ Functor,+ Monad,+ MonadIO,+ MonadState DecodeState,+ MonadAnyCont IO,+ ScopeAnyCont+ )++runDecodeAST :: DecodeAST a -> IO a+runDecodeAST d = flip evalStateT initialDecode . flip runAnyContT return . unDecodeAST $ d++localScope :: DecodeAST a -> DecodeAST a+localScope (DecodeAST x) = DecodeAST (tweak x)+ where tweak x = do+ modify (\s@DecodeState { localNameCounter = Nothing } -> s { localNameCounter = Just 0 })+ r <- x+ modify (\s@DecodeState { localNameCounter = Just _ } -> s { localNameCounter = Nothing })+ return r++getName :: (Ptr a -> IO CString)+ -> Ptr a+ -> (DecodeState -> NameMap a)+ -> DecodeAST Word+ -> DecodeAST A.Name+getName getCString v getNameMap generate = do+ name <- liftIO $ do+ n <- getCString v+ if n == nullPtr then return "" else decodeM n+ if name /= "" + then+ return $ A.Name name+ else+ A.UnName <$> do+ nm <- gets getNameMap+ maybe generate return $ Map.lookup v nm++getValueName :: FFI.DescendentOf FFI.Value v => Ptr v -> (DecodeState -> NameMap v) -> DecodeAST Word -> DecodeAST A.Name+getValueName = getName (FFI.getValueName . FFI.upCast)++getLocalName :: FFI.DescendentOf FFI.Value v => Ptr v -> DecodeAST A.Name+getLocalName v' = do+ let v = FFI.upCast v'+ getValueName v localVarNum $ do+ nm <- gets localVarNum+ Just n <- gets localNameCounter+ modify $ \s -> s { localNameCounter = Just (1 + n), localVarNum = Map.insert v n nm }+ return n++getGlobalName :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST A.Name+getGlobalName v' = do+ let v = FFI.upCast v'+ getValueName v globalVarNum $ do+ nm <- gets globalVarNum+ let n = fromIntegral $ Map.size nm+ modify $ \s -> s { globalVarNum = Map.insert v n nm }+ return n+++getTypeName :: Ptr FFI.Type -> DecodeAST A.Name+getTypeName t = do+ getName FFI.getStructName t namedTypeNum $ do+ nm <- gets namedTypeNum+ let n = fromIntegral $ Map.size nm+ modify $ \s -> s { namedTypeNum = Map.insert t n nm }+ return n++saveNamedType :: Ptr FFI.Type -> DecodeAST ()+saveNamedType t = do+ modify $ \s -> s { typesToDefine = t Seq.<| typesToDefine s }++getMetadataNodeID :: Ptr FFI.MDNode -> DecodeAST A.MetadataNodeID+getMetadataNodeID p = do+ mdns <- gets metadataNodes+ case Map.lookup p mdns of+ Just r -> return r+ Nothing -> do+ let r = A.MetadataNodeID (fromIntegral (Map.size mdns))+ modify $ \s -> s { + metadataNodesToDefine = (r, p) Seq.<| metadataNodesToDefine s,+ metadataNodes = Map.insert p r (metadataNodes s)+ }+ return r++takeTypeToDefine :: DecodeAST (Maybe (Ptr FFI.Type))+takeTypeToDefine = state $ \s -> case Seq.viewr (typesToDefine s) of+ remaining Seq.:> t -> (Just t, s { typesToDefine = remaining })+ _ -> (Nothing, s)++takeMetadataNodeToDefine :: DecodeAST (Maybe (A.MetadataNodeID, Ptr FFI.MDNode))+takeMetadataNodeToDefine = state $ \s -> case Seq.viewr (metadataNodesToDefine s) of+ remaining Seq.:> md -> (Just md, s { metadataNodesToDefine = remaining })+ _ -> (Nothing, s) ++instance DecodeM DecodeAST A.Name (Ptr FFI.BasicBlock) where+ decodeM = getLocalName++getAttributeGroupID :: FFI.FunctionAttributeSet -> DecodeAST A.A.GroupID+getAttributeGroupID p = do+ ids <- gets functionAttributeSetIDs+ case Map.lookup p ids of+ Just r -> return r+ Nothing -> do+ let r = A.A.GroupID (fromIntegral (Map.size ids))+ modify $ \s -> s { functionAttributeSetIDs = Map.insert p r (functionAttributeSetIDs s) }+ return r
+ src/LLVM/Internal/Diagnostic.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE+ TemplateHaskell,+ MultiParamTypeClasses+ #-} +module LLVM.Internal.Diagnostic where++import LLVM.Prelude++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import qualified LLVM.Internal.FFI.SMDiagnostic as FFI++import Control.Exception++import Foreign.Ptr++import LLVM.Diagnostic+import LLVM.Internal.Coding+import LLVM.Internal.String ()++genCodingInstance [t| DiagnosticKind |] ''FFI.DiagnosticKind [+ (FFI.diagnosticKindError, ErrorKind),+ (FFI.diagnosticKindWarning, WarningKind),+ (FFI.diagnosticKindNote, NoteKind)+ ]++withSMDiagnostic :: (Ptr FFI.SMDiagnostic -> IO a) -> IO a+withSMDiagnostic = bracket FFI.createSMDiagnostic FFI.disposeSMDiagnostic++getDiagnostic :: Ptr FFI.SMDiagnostic -> IO Diagnostic+getDiagnostic p = do+ l <- decodeM =<< FFI.getSMDiagnosticLineNo p+ c <- decodeM =<< FFI.getSMDiagnosticColumnNo p+ k <- decodeM =<< FFI.getSMDiagnosticKind p+ f <- decodeM $ FFI.getSMDiagnosticFilename p+ m <- decodeM $ FFI.getSMDiagnosticMessage p+ lc <- decodeM $ FFI.getSMDiagnosticLineContents p+ return $ Diagnostic { + lineNumber = l, columnNumber = c, diagnosticKind = k, filename = f, message = m, lineContents = lc+ }+
+ src/LLVM/Internal/EncodeAST.hs view
@@ -0,0 +1,159 @@+{-# LANGUAGE+ GeneralizedNewtypeDeriving,+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+module LLVM.Internal.EncodeAST where++import LLVM.Prelude++import Control.Exception+import Control.Monad.AnyCont+import Control.Monad.Error.Class+import Control.Monad.State+import Control.Monad.Trans.Except++import Foreign.Ptr+import Foreign.C++import Data.Map (Map)+import qualified Data.Map as Map++import qualified LLVM.Internal.FFI.Attribute as FFI +import qualified LLVM.Internal.FFI.Builder as FFI+import qualified LLVM.Internal.FFI.GlobalValue as FFI+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI+import qualified LLVM.Internal.FFI.Value as FFI++import qualified LLVM.AST as A+import qualified LLVM.AST.Attribute as A.A++import LLVM.Internal.Context+import LLVM.Internal.Coding+import LLVM.Internal.String ()++data LocalValue+ = ForwardValue (Ptr FFI.Value)+ | DefinedValue (Ptr FFI.Value)++data EncodeState = EncodeState {+ encodeStateBuilder :: Ptr FFI.Builder,+ encodeStateContext :: Context,+ encodeStateLocals :: Map A.Name LocalValue,+ encodeStateGlobals :: Map A.Name (Ptr FFI.GlobalValue),+ encodeStateAllBlocks :: Map (A.Name, A.Name) (Ptr FFI.BasicBlock),+ encodeStateBlocks :: Map A.Name (Ptr FFI.BasicBlock),+ encodeStateMDNodes :: Map A.MetadataNodeID (Ptr FFI.MDNode),+ encodeStateNamedTypes :: Map A.Name (Ptr FFI.Type),+ encodeStateAttributeGroups :: Map A.A.GroupID FFI.FunctionAttributeSet,+ encodeStateCOMDATs :: Map String (Ptr FFI.COMDAT)+ }++newtype EncodeAST a = EncodeAST { unEncodeAST :: AnyContT (ExceptT String (StateT EncodeState IO)) a }+ deriving (+ Functor,+ Applicative,+ Monad,+ MonadIO,+ MonadState EncodeState,+ MonadError String,+ MonadAnyCont IO,+ ScopeAnyCont+ )++lookupNamedType :: A.Name -> EncodeAST (Ptr FFI.Type)+lookupNamedType n = do+ t <- gets $ Map.lookup n . encodeStateNamedTypes+ maybe (throwError $ "reference to undefined type: " ++ show n) return t++defineType :: A.Name -> Ptr FFI.Type -> EncodeAST ()+defineType n t = modify $ \s -> s { encodeStateNamedTypes = Map.insert n t (encodeStateNamedTypes s) }++runEncodeAST :: Context -> EncodeAST a -> ExceptT String IO a+runEncodeAST context@(Context ctx) (EncodeAST a) = ExceptT $+ bracket (FFI.createBuilderInContext ctx) FFI.disposeBuilder $ \builder -> do+ let initEncodeState = EncodeState {+ encodeStateBuilder = builder,+ encodeStateContext = context,+ encodeStateLocals = Map.empty,+ encodeStateGlobals = Map.empty,+ encodeStateAllBlocks = Map.empty,+ encodeStateBlocks = Map.empty,+ encodeStateMDNodes = Map.empty,+ encodeStateNamedTypes = Map.empty,+ encodeStateAttributeGroups = Map.empty,+ encodeStateCOMDATs = Map.empty+ }+ flip evalStateT initEncodeState . runExceptT . flip runAnyContT return $ a++withName :: A.Name -> (CString -> IO a) -> IO a+withName (A.Name n) = withCString n+withName (A.UnName _) = withCString ""++instance MonadAnyCont IO m => EncodeM m A.Name CString where+ encodeM (A.Name n) = encodeM n+ encodeM _ = encodeM ""++phase :: EncodeAST a -> EncodeAST (EncodeAST a)+phase p = do+ let s0 `withLocalsFrom` s1 = s0 {+ encodeStateLocals = encodeStateLocals s1,+ encodeStateBlocks = encodeStateBlocks s1+ }+ s <- get+ return $ do+ s' <- get+ put $ s' `withLocalsFrom` s+ r <- p+ modify (`withLocalsFrom` s')+ return r++defineLocal :: FFI.DescendentOf FFI.Value v => A.Name -> Ptr v -> EncodeAST ()+defineLocal n v' = do+ let v = FFI.upCast v'+ def <- gets $ Map.lookup n . encodeStateLocals+ case def of+ Just (ForwardValue dummy) -> liftIO $ FFI.replaceAllUsesWith dummy v+ _ -> return ()+ modify $ \b -> b { encodeStateLocals = Map.insert n (DefinedValue v) (encodeStateLocals b) }++defineGlobal :: FFI.DescendentOf FFI.GlobalValue v => A.Name -> Ptr v -> EncodeAST ()+defineGlobal n v = modify $ \b -> b { encodeStateGlobals = Map.insert n (FFI.upCast v) (encodeStateGlobals b) }++defineMDNode :: A.MetadataNodeID -> Ptr FFI.MDNode -> EncodeAST ()+defineMDNode n v = modify $ \b -> b { encodeStateMDNodes = Map.insert n (FFI.upCast v) (encodeStateMDNodes b) }++defineAttributeGroup :: A.A.GroupID -> FFI.FunctionAttributeSet -> EncodeAST ()+defineAttributeGroup gid attrs = modify $ \b -> b { encodeStateAttributeGroups = Map.insert gid attrs (encodeStateAttributeGroups b) }++defineCOMDAT :: String -> Ptr FFI.COMDAT -> EncodeAST ()+defineCOMDAT name cd = modify $ \b -> b { encodeStateCOMDATs = Map.insert name cd (encodeStateCOMDATs b) }++refer :: (Show n, Ord n) => (EncodeState -> Map n v) -> n -> EncodeAST v -> EncodeAST v+refer r n f = do+ mop <- gets $ Map.lookup n . r+ maybe f return mop++undefinedReference :: Show n => String -> n -> EncodeAST a+undefinedReference m n = throwError $ "reference to undefined " ++ m ++ ": " ++ show n++referOrThrow :: (Show n, Ord n) => (EncodeState -> Map n v) -> String -> n -> EncodeAST v+referOrThrow r m n = refer r n $ undefinedReference m n++referGlobal = referOrThrow encodeStateGlobals "global"+referMDNode = referOrThrow encodeStateMDNodes "metadata node"+referAttributeGroup = referOrThrow encodeStateAttributeGroups "attribute group"+referCOMDAT = referOrThrow encodeStateCOMDATs "COMDAT"++defineBasicBlock :: A.Name -> A.Name -> Ptr FFI.BasicBlock -> EncodeAST ()+defineBasicBlock fn n b = modify $ \s -> s {+ encodeStateBlocks = Map.insert n b (encodeStateBlocks s),+ encodeStateAllBlocks = Map.insert (fn, n) b (encodeStateAllBlocks s)+}++instance EncodeM EncodeAST A.Name (Ptr FFI.BasicBlock) where+ encodeM = referOrThrow encodeStateBlocks "block"++getBlockForAddress :: A.Name -> A.Name -> EncodeAST (Ptr FFI.BasicBlock)+getBlockForAddress fn n = referOrThrow encodeStateAllBlocks "blockaddress" (fn, n)+
+ src/LLVM/Internal/ExecutionEngine.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE+ MultiParamTypeClasses,+ FunctionalDependencies,+ RankNTypes+ #-}+module LLVM.Internal.ExecutionEngine where++import LLVM.Prelude++import Control.Exception+import Control.Monad.IO.Class+import Control.Monad.AnyCont+import Control.Monad.Trans.Except++import Data.IORef+import Foreign.Ptr+import Foreign.C (CUInt, CString)+import Foreign.Marshal.Alloc (allocaBytes)++import qualified LLVM.Internal.FFI.PtrHierarchy as FFI+import qualified LLVM.Internal.FFI.ExecutionEngine as FFI+import qualified LLVM.Internal.FFI.Module as FFI+import qualified LLVM.Internal.FFI.LLVMCTypes as FFI++import LLVM.Internal.Module+import LLVM.Internal.Context+import LLVM.Internal.Coding+import qualified LLVM.CodeModel as CodeModel+import LLVM.Internal.Target+import qualified LLVM.AST as A++removeModule :: Ptr FFI.ExecutionEngine -> Ptr FFI.Module -> IO ()+removeModule e m = flip runAnyContT return $ do+ d0 <- alloca+ d1 <- alloca+ r <- liftIO $ FFI.removeModule e m d0 d1+ when (r /= 0) $ fail "FFI.removeModule failure"++-- | a 'ExecutableModule' e represents a 'Module' which is currently "in" an+-- 'ExecutionEngine', and so the functions of which may be executed.+data ExecutableModule e = ExecutableModule e (Ptr FFI.Module)++-- | <http://llvm.org/doxygen/classllvm_1_1ExecutionEngine.html>+class ExecutionEngine e f | e -> f where+ withModuleInEngine :: e -> Module -> (ExecutableModule e -> IO a) -> IO a+ getFunction :: ExecutableModule e -> A.Name -> IO (Maybe f)++instance ExecutionEngine (Ptr FFI.ExecutionEngine) (FunPtr ()) where+ withModuleInEngine e m f = do+ m' <- readModule m+ bracket_ (FFI.addModule e m') (removeModule e m') (f (ExecutableModule e m'))+ getFunction (ExecutableModule e m) (A.Name name) = flip runAnyContT return $ do+ name <- encodeM name+ f <- liftIO $ FFI.getNamedFunction m name+ if f == nullPtr + then + return Nothing+ else+ do+ p <- liftIO $ FFI.getPointerToGlobal e (FFI.upCast f)+ return $ if p == nullPtr then Nothing else Just (castPtrToFunPtr p)++withExecutionEngine :: + Context ->+ Maybe (Ptr FFI.Module) -> + (Ptr (Ptr FFI.ExecutionEngine) -> Ptr FFI.Module -> Ptr (FFI.OwnerTransfered CString) -> IO CUInt) ->+ (Ptr FFI.ExecutionEngine -> IO a) ->+ IO a+withExecutionEngine c m createEngine f = flip runAnyContT return $ do+ liftIO initializeNativeTarget+ outExecutionEngine <- alloca+ outErrorCStringPtr <- alloca+ dummyModule <- maybe (anyContToM $ liftM (either undefined id) . runExceptT+ . withModuleFromAST c (A.Module "" "" Nothing Nothing []))+ (liftIO . newModule) m+ dummyModule' <- readModule dummyModule+ r <- liftIO $ createEngine outExecutionEngine dummyModule' outErrorCStringPtr+ when (r /= 0) $ fail =<< decodeM outErrorCStringPtr+ executionEngine <- anyContToM $ bracket (peek outExecutionEngine) FFI.disposeExecutionEngine+ liftIO $ removeModule executionEngine dummyModule'+ liftIO $ f executionEngine++data MCJITState+ = Deferred (forall a . Module -> (Ptr FFI.ExecutionEngine -> IO a) -> IO a)+ | Constructed (Ptr FFI.ExecutionEngine)++-- | <http://llvm.org/doxygen/classllvm_1_1MCJIT.html>+-- <http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html>+-- N.B. - the LLVM MCJIT does not current support adding multiple+-- modules to any one instance of the MCJIT.+newtype MCJIT = MCJIT (IORef MCJITState)++-- | bracket the creation and destruction of an 'MCJIT'+withMCJIT :: + Context+ -> Maybe Word -- ^ optimization level+ -> Maybe CodeModel.Model+ -> Maybe Bool -- ^ True to disable frame pointer elimination+ -> Maybe Bool -- ^ True to enable fast instruction selection+-- -> Maybe MemoryManager -- llvm-hs doesn't support this yet+ -> (MCJIT -> IO a)+ -> IO a+withMCJIT c opt cm fpe fisel f = do+ FFI.linkInMCJIT+ let createMCJITCompilerForModule e m s = do+ size <- FFI.getMCJITCompilerOptionsSize+ allocaBytes (fromIntegral size) $ \p -> do+ FFI.initializeMCJITCompilerOptions p size+ maybe (return ()) (FFI.setMCJITCompilerOptionsOptLevel p <=< encodeM) opt+ maybe (return ()) (FFI.setMCJITCompilerOptionsCodeModel p <=< encodeM) cm+ maybe (return ()) (FFI.setMCJITCompilerOptionsNoFramePointerElim p <=< encodeM) fpe+ maybe (return ()) (FFI.setMCJITCompilerOptionsEnableFastISel p <=< encodeM) fisel+ FFI.createMCJITCompilerForModule e m p size s+ t <- newIORef (Deferred $ \mod f -> do m' <- readModule mod+ withExecutionEngine c (Just m') createMCJITCompilerForModule f)+ f (MCJIT t)++instance ExecutionEngine MCJIT (FunPtr ()) where+ withModuleInEngine (MCJIT s) m f = do+ jitState <- readIORef s+ let f' (ExecutableModule _ m) = f (ExecutableModule (MCJIT s) m)+ case jitState of+ Deferred c -> c m $ \e -> + bracket_ + (writeIORef s (Constructed e))+ (writeIORef s jitState)+ (withModuleInEngine e m f')+ Constructed e -> withModuleInEngine e m f'++ getFunction (ExecutableModule (MCJIT r) m) n = do+ s <- liftIO $ readIORef r+ case s of+ Deferred _ -> return Nothing+ Constructed e -> getFunction (ExecutableModule e m) n
+ src/LLVM/Internal/FFI/Analysis.h view
@@ -0,0 +1,11 @@+#ifndef __LLVM_INTERNAL_FFI__ANALYSIS__H__+#define __LLVM_INTERNAL_FFI__ANALYSIS__H__++#include "llvm-c/Analysis.h"++#define LLVM_HS_FOR_EACH_VERIFIER_FAILURE_ACTION(macro) \+ macro(AbortProcess) \+ macro(PrintMessage) \+ macro(ReturnStatus)++#endif
+ src/LLVM/Internal/FFI/Analysis.hs view
@@ -0,0 +1,15 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}+module LLVM.Internal.FFI.Analysis where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.Module++foreign import ccall unsafe "LLVMVerifyModule" verifyModule ::+ Ptr Module -> VerifierFailureAction -> Ptr (OwnerTransfered CString) -> IO LLVMBool
+ src/LLVM/Internal/FFI/Assembly.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}++-- | Functions to read and write textual LLVM assembly+module LLVM.Internal.FFI.Assembly where++import LLVM.Prelude++import LLVM.Internal.FFI.Context+import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.MemoryBuffer+import LLVM.Internal.FFI.Module+import LLVM.Internal.FFI.PtrHierarchy++import Foreign.C+import Foreign.Ptr++-- | Use LLVM's parser to parse a string of llvm assembly in a memory buffer to get a module+foreign import ccall unsafe "LLVM_Hs_ParseLLVMAssembly" parseLLVMAssembly ::+ Ptr Context -> OwnerTransfered (Ptr MemoryBuffer) -> Ptr (OwnerTransfered CString) -> IO (Ptr Module)+++-- | LLVM's serializer to generate a string of llvm assembly from a module+foreign import ccall unsafe "LLVM_Hs_WriteLLVMAssembly" writeLLVMAssembly ::+ Ptr Module -> Ptr RawOStream -> IO ()+++
+ src/LLVM/Internal/FFI/AssemblyC.cpp view
@@ -0,0 +1,28 @@+#define __STDC_LIMIT_MACROS+#include "llvm/AsmParser/Parser.h"+#include "llvm/IR/LLVMContext.h"+#include "llvm/IR/Module.h"+#include "llvm/Pass.h"+#include "llvm/Support/MemoryBuffer.h"+#include "llvm/Support/SourceMgr.h"+#include "llvm/Support/raw_ostream.h"++#include "llvm-c/Core.h"+#include "llvm-c/IRReader.h"++using namespace llvm;++extern "C" {++LLVMModuleRef LLVM_Hs_ParseLLVMAssembly(LLVMContextRef context,+ LLVMMemoryBufferRef memoryBuffer,+ char **error) {+ LLVMModuleRef M;+ LLVMParseIRInContext(context, memoryBuffer, &M, error);+ return M;+}++void LLVM_Hs_WriteLLVMAssembly(LLVMModuleRef module, raw_ostream &os) {+ os << *unwrap(module);+}+}
+ src/LLVM/Internal/FFI/Attribute.h view
@@ -0,0 +1,69 @@+#ifndef __LLVM_INTERNAL_FFI__ATTRIBUTES__H__+#define __LLVM_INTERNAL_FFI__ATTRIBUTES__H__+++// The last three arguments are flags indicating if this is a+// parameter attribute, function result attribute or function attribute.+#define LLVM_HS_FOR_EACH_ATTRIBUTE_KIND(macro) \+ macro(None,F,F,F) \+ macro(Alignment,T,T,F) \+ macro(AllocSize,F,F,T) \+ macro(AlwaysInline,F,F,T) \+ macro(ArgMemOnly,F,F,T) \+ macro(Builtin,F,F,T) \+ macro(ByVal,T,F,F) \+ macro(Cold,F,F,T) \+ macro(Convergent,F,F,T) \+ macro(Dereferenceable,T,T,F) \+ macro(DereferenceableOrNull,T,T,F) \+ macro(InAlloca,T,F,F) \+ macro(InReg,T,T,F) \+ macro(InaccessibleMemOnly,F,F,T) \+ macro(InaccessibleMemOrArgMemOnly,F,F,T) \+ macro(InlineHint,F,F,T) \+ macro(JumpTable,F,F,T) \+ macro(MinSize,F,F,T) \+ macro(Naked,F,F,T) \+ macro(Nest,T,F,F) \+ macro(NoAlias,T,T,F) \+ macro(NoBuiltin,F,F,T) \+ macro(NoCapture,T,F,F) \+ macro(NoDuplicate,F,F,T) \+ macro(NoImplicitFloat,F,F,T) \+ macro(NoInline,F,F,T) \+ macro(NoRecurse,F,F,T) \+ macro(NoRedZone,F,F,T) \+ macro(NoReturn,F,F,T) \+ macro(NoUnwind,F,F,T) \+ macro(NonLazyBind,F,F,T) \+ macro(NonNull,T,T,F) \+ macro(OptimizeForSize,F,F,T) \+ macro(OptimizeNone,F,F,T) \+ macro(ReadNone,T,F,T) \+ macro(ReadOnly,T,F,T) \+ macro(Returned,T,F,F) \+ macro(ReturnsTwice,F,F,T) \+ macro(SExt,T,T,F) \+ macro(SafeStack,F,F,T) \+ macro(SanitizeAddress,F,F,T) \+ macro(SanitizeMemory,F,F,T) \+ macro(SanitizeThread,F,F,T) \+ macro(StackAlignment,F,F,T) \+ macro(StackProtect,F,F,T) \+ macro(StackProtectReq,F,F,T) \+ macro(StackProtectStrong,F,F,T) \+ macro(StructRet,T,F,F) \+ macro(SwiftError,T,F,F) \+ macro(SwiftSelf,T,F,F) \+ macro(UWTable,F,F,T) \+ macro(WriteOnly,T,F,T) \+ macro(ZExt,T,T,F) \+ macro(EndAttrKinds,F,F,F)++typedef enum {+#define ENUM_CASE(x,p,r,f) LLVM_Hs_AttributeKind_ ## x,+LLVM_HS_FOR_EACH_ATTRIBUTE_KIND(ENUM_CASE)+#undef ENUM_CASE+} LLVM_Hs_AttributeKind;++#endif
+ src/LLVM/Internal/FFI/Attribute.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}+module LLVM.Internal.FFI.Attribute where++import LLVM.Prelude++import Foreign.C+import Foreign.Ptr++import LLVM.Internal.FFI.Context+import LLVM.Internal.FFI.LLVMCTypes++type Index = CInt+type Slot = CUInt+type IntValue = Word64++{-+Data model:+llvm::Attribute is one function or parameter attribute++llvm::AttributeSet is a mess.+It's used to represent, at different times:+a) the set of parameter attributes on a parameter+b) the set of parameter attributes for a functions return value+c) the set of function attributes for a function+d) All of the above++It is only possible to enumerate the attributes in an attribute set+given a "slot".++Encode path:+Use AttrBuilder on the C++ side only, to implement [Attribute] -> AttributeSet+AttributeSets -> whole AttributeSet++Decode strategy:+Store maps of AttributeSetImpl (Mess | Parameter | Function),+keyed by raw pointer. Expect Parameter and Function AttributeSetImpls+to have only one slot. Use the per-slot iterators to decode them+-}++data MixedAttributeType+data FunctionAttributeType+data ParameterAttributeType+data AttributeImpl a+data AttributeSetImpl a++type Attribute a = Ptr (AttributeImpl a)+type FunctionAttribute = Attribute FunctionAttributeType+type ParameterAttribute = Attribute ParameterAttributeType++type AttributeSet a = Ptr (AttributeSetImpl a)+type MixedAttributeSet = AttributeSet MixedAttributeType+type FunctionAttributeSet = AttributeSet FunctionAttributeType+type ParameterAttributeSet = AttributeSet ParameterAttributeType++forgetAttributeType :: AttributeSet a -> AttributeSet MixedAttributeType+forgetAttributeType = castPtr++functionIndex :: Index+functionIndex = -1+returnIndex :: Index+returnIndex = 0++foreign import ccall unsafe "LLVM_Hs_AttributeKindAsEnum" parameterAttributeKindAsEnum ::+ ParameterAttribute -> IO ParameterAttributeKind++foreign import ccall unsafe "LLVM_Hs_AttributeKindAsEnum" functionAttributeKindAsEnum ::+ FunctionAttribute -> IO FunctionAttributeKind++foreign import ccall unsafe "LLVM_Hs_IsStringAttribute" isStringAttribute ::+ Attribute a -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_AttributeKindAsString" attributeKindAsString ::+ Attribute a -> Ptr CSize -> IO (Ptr CChar)++foreign import ccall unsafe "LLVM_Hs_AttributeValueAsString" attributeValueAsString ::+ Attribute a -> Ptr CSize -> IO (Ptr CChar)++foreign import ccall unsafe "LLVM_Hs_AttributeValueAsInt" attributeValueAsInt ::+ Attribute a -> IO Word64++foreign import ccall unsafe "LLVM_Hs_AttributeSetNumSlots" attributeSetNumSlots ::+ AttributeSet a -> IO Slot++foreign import ccall unsafe "LLVM_Hs_AttributeSetSlotIndex" attributeSetSlotIndex ::+ AttributeSet a -> Slot -> IO Index++foreign import ccall unsafe "LLVM_Hs_AttributeSetSlotAttributes" attributeSetSlotAttributes ::+ MixedAttributeSet -> Slot -> IO (AttributeSet a)++foreign import ccall unsafe "LLVM_Hs_AttributeSetGetAttributes" attributeSetGetAttributes ::+ AttributeSet a -> Slot -> Ptr CUInt -> IO (Ptr (Attribute a))++foreign import ccall unsafe "LLVM_Hs_GetAttributeSet" getAttributeSet ::+ Ptr Context -> Index -> Ptr (AttrBuilder a) -> IO (AttributeSet a)++foreign import ccall unsafe "LLVM_Hs_MixAttributeSets" mixAttributeSets ::+ Ptr Context -> Ptr MixedAttributeSet -> CUInt -> IO MixedAttributeSet++data AttrBuilder a+type FunctionAttrBuilder = AttrBuilder FunctionAttributeType+type ParameterAttrBuilder = AttrBuilder ParameterAttributeType++foreign import ccall unsafe "LLVM_Hs_GetAttrBuilderSize" getAttrBuilderSize ::+ CSize++foreign import ccall unsafe "LLVM_Hs_ConstructAttrBuilder" constructAttrBuilder ::+ Ptr Word8 -> IO (Ptr (AttrBuilder a))++foreign import ccall unsafe "LLVM_Hs_DestroyAttrBuilder" destroyAttrBuilder ::+ Ptr (AttrBuilder a) -> IO ()++foreign import ccall unsafe "LLVM_Hs_AttrBuilderAddAttributeKind" attrBuilderAddFunctionAttributeKind ::+ Ptr FunctionAttrBuilder -> FunctionAttributeKind -> IO ()++foreign import ccall unsafe "LLVM_Hs_AttrBuilderAddAttributeKind" attrBuilderAddParameterAttributeKind ::+ Ptr ParameterAttrBuilder -> ParameterAttributeKind -> IO ()++foreign import ccall unsafe "LLVM_Hs_AttrBuilderAddStringAttribute" attrBuilderAddStringAttribute ::+ Ptr FunctionAttrBuilder -> Ptr CChar -> CSize -> Ptr CChar -> CSize -> IO ()++foreign import ccall unsafe "LLVM_Hs_AttrBuilderAddAlignment" attrBuilderAddAlignment ::+ Ptr ParameterAttrBuilder -> Word64 -> IO ()++foreign import ccall unsafe "LLVM_Hs_AttrBuilderAddStackAlignment" attrBuilderAddStackAlignment ::+ Ptr FunctionAttrBuilder -> Word64 -> IO ()++-- The CInt is 0 if the last value is null and 1 otherwise+foreign import ccall unsafe "LLVM_Hs_AttrBuilderAddAllocSize" attrBuilderAddAllocSize' ::+ Ptr FunctionAttrBuilder -> CUInt -> CUInt -> LLVMBool -> IO ()++attrBuilderAddAllocSize :: Ptr FunctionAttrBuilder -> CUInt -> (CUInt, LLVMBool) -> IO ()+attrBuilderAddAllocSize b i (y, isJust) = attrBuilderAddAllocSize' b i y isJust++foreign import ccall unsafe "LLVM_Hs_AttrBuilderAddDereferenceableAttr" attrBuilderAddDereferenceable ::+ Ptr ParameterAttrBuilder -> Word64 -> IO ()++foreign import ccall unsafe "LLVM_Hs_AttrBuilderAddDereferenceableOrNullAttr" attrBuilderAddDereferenceableOrNull ::+ Ptr ParameterAttrBuilder -> Word64 -> IO ()++foreign import ccall unsafe "LLVM_Hs_AttributeGetAllocSizeArgs" attributeGetAllocSizeArgs ::+ FunctionAttribute -> Ptr CUInt -> Ptr CUInt -> IO LLVMBool
+ src/LLVM/Internal/FFI/AttributeC.cpp view
@@ -0,0 +1,145 @@+#define __STDC_LIMIT_MACROS+#include "llvm/IR/LLVMContext.h"+#include "LLVM/Internal/FFI/AttributeC.hpp"++extern "C" {++static_assert(sizeof(AttributeSet) == sizeof(AttributeSetImpl *),+ "AttributeSet implementation has changed");++static_assert(sizeof(Attribute) == sizeof(AttributeImpl *),+ "Attribute implementation has changed");++unsigned LLVM_Hs_AttributeSetNumSlots(const AttributeSetImpl *a) {+ return unwrap(a).getNumSlots();+}++int LLVM_Hs_AttributeSetSlotIndex(const AttributeSetImpl *a, unsigned slot) {+ return unwrap(a).getSlotIndex(slot);+}++const AttributeSetImpl *LLVM_Hs_AttributeSetSlotAttributes(const AttributeSetImpl *a, unsigned slot) {+ return wrap(unwrap(a).getSlotAttributes(slot));+}++const AttributeSetImpl *LLVM_Hs_GetSlotAttributeSet(+ LLVMContextRef context,+ unsigned index,+ const AttributeImpl **attributes,+ unsigned length+) {+ AttrBuilder builder;+ for (unsigned i = 0; i < length; i++) builder.addAttribute(unwrap(attributes[i]));+ return wrap(AttributeSet::get(*unwrap(context), index, builder));+}++const AttributeImpl *const *LLVM_Hs_AttributeSetGetAttributes(AttributeSetImpl *asi, unsigned slot, unsigned *length) {+ AttributeSet as = unwrap(asi);+ ArrayRef<Attribute>::iterator b = as.begin(slot), e = as.end(slot);+ *length = e - b;+ return reinterpret_cast<const AttributeImpl *const *>(b);+}++#define CHECK(name,p,r,f) \+ static_assert( \+ unsigned(llvm::Attribute::name) == unsigned(LLVM_Hs_AttributeKind_ ## name), \+ "LLVM_Hs_AttributeKind enum out of sync w/ llvm::Attribute::AttrKind for " #name \+ );+ LLVM_HS_FOR_EACH_ATTRIBUTE_KIND(CHECK)+#undef CHECK++unsigned LLVM_Hs_AttributeKindAsEnum(const AttributeImpl *a) {+ return unwrap(a).getKindAsEnum();+}++uint64_t LLVM_Hs_AttributeValueAsInt(const AttributeImpl *a) {+ return unwrap(a).getValueAsInt();+}++LLVMBool LLVM_Hs_IsStringAttribute(const AttributeImpl *a) {+ return unwrap(a).isStringAttribute();+}++const char *LLVM_Hs_AttributeKindAsString(const AttributeImpl *a, size_t &l) {+ const StringRef s = unwrap(a).getKindAsString();+ l = s.size();+ return s.data();+}++const char *LLVM_Hs_AttributeValueAsString(const AttributeImpl *a, size_t &l) {+ const StringRef s = unwrap(a).getValueAsString();+ l = s.size();+ return s.data();+}++const AttributeSetImpl *LLVM_Hs_GetAttributeSet(LLVMContextRef context, unsigned index, const AttrBuilder &ab) {+ return wrap(AttributeSet::get(*unwrap(context), index, ab));+}++const AttributeSetImpl *LLVM_Hs_MixAttributeSets(+ LLVMContextRef context, const AttributeSetImpl **as, unsigned n+) {+ return wrap(+ AttributeSet::get(+ *unwrap(context),+ ArrayRef<AttributeSet>(reinterpret_cast<const AttributeSet *>(as), n)+ )+ );+}++size_t LLVM_Hs_GetAttrBuilderSize() { return sizeof(AttrBuilder); }++AttrBuilder *LLVM_Hs_ConstructAttrBuilder(char *p) {+ return new(p) AttrBuilder();+}++void LLVM_Hs_DestroyAttrBuilder(AttrBuilder *a) {+ a->~AttrBuilder();+}++void LLVM_Hs_AttrBuilderAddAttributeKind(AttrBuilder &ab, unsigned kind) {+ ab.addAttribute(Attribute::AttrKind(kind));+}++void LLVM_Hs_AttrBuilderAddStringAttribute(+ AttrBuilder &ab, const char *kind, size_t kind_len, const char *value, size_t value_len+) {+ ab.addAttribute(StringRef(kind, kind_len), StringRef(value, value_len));+}++void LLVM_Hs_AttrBuilderAddAlignment(AttrBuilder &ab, uint64_t v) {+ ab.addAlignmentAttr(v);+}++void LLVM_Hs_AttrBuilderAddStackAlignment(AttrBuilder &ab, uint64_t v) {+ ab.addStackAlignmentAttr(v);+}++void LLVM_Hs_AttrBuilderAddAllocSize(AttrBuilder &ab, unsigned x, LLVMBool optionalIsThere, unsigned y) {+ if (optionalIsThere) {+ ab.addAllocSizeAttr(x, y);+ } else {+ ab.addAllocSizeAttr(x, Optional<unsigned>());+ }+}++void LLVM_Hs_AttrBuilderAddDereferenceableAttr(AttrBuilder &ab, uint64_t v) {+ ab.addDereferenceableAttr(v);+}++void LLVM_Hs_AttrBuilderAddDereferenceableOrNullAttr(AttrBuilder &ab, uint64_t v) {+ ab.addDereferenceableOrNullAttr(v);+}++LLVMBool LLVM_Hs_AttributeGetAllocSizeArgs(const AttributeImpl* a, unsigned* x, unsigned* y) {+ auto pair = unwrap(a).getAllocSizeArgs();+ *x = pair.first;+ if (pair.second.hasValue()) {+ *y = pair.second.getValue();+ return 1;+ } else {+ return 0;+ }+}++}
+ src/LLVM/Internal/FFI/AttributeC.hpp view
@@ -0,0 +1,24 @@+#ifndef __LLVM_ATTRIBUTE_C_HPP__+#define __LLVM_ATTRIBUTE_C_HPP__+#define __STDC_LIMIT_MACROS+#include "llvm/IR/Attributes.h"+#include "LLVM/Internal/FFI/Attribute.h"+using namespace llvm;++inline AttributeSet unwrap(const AttributeSetImpl *asi) {+ return *reinterpret_cast<const AttributeSet *>(&asi);+}++inline const AttributeSetImpl *wrap(AttributeSet as) {+ return *reinterpret_cast<const AttributeSetImpl **>(&as);+}++inline Attribute unwrap(const AttributeImpl *ai) {+ return *reinterpret_cast<const Attribute *>(&ai);+}++inline const AttributeImpl *wrap(Attribute a) {+ return *reinterpret_cast<const AttributeImpl **>(&a);+}++#endif
+ src/LLVM/Internal/FFI/BasicBlock.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE+ ForeignFunctionInterface,+ MultiParamTypeClasses+ #-}++-- | <http://llvm.org/doxygen/classllvm_1_1BasicBlock.html>+module LLVM.Internal.FFI.BasicBlock where++import LLVM.Prelude++import Foreign.Ptr++import LLVM.Internal.FFI.PtrHierarchy++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueBasicBlock.html#gab57c996ff697ef40966432055ae47a4e>+foreign import ccall unsafe "LLVMIsABasicBlock" isABasicBlock ::+ Ptr Value -> IO (Ptr BasicBlock)++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueBasicBlock.html#ga754e45f69f4b784b658d9e379943f354>+foreign import ccall unsafe "LLVMGetBasicBlockTerminator" getBasicBlockTerminator ::+ Ptr BasicBlock -> IO (Ptr Instruction)++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueBasicBlock.html#ga9baf824cd325ad211027b23fce8a7494>+foreign import ccall unsafe "LLVMGetFirstInstruction" getFirstInstruction ::+ Ptr BasicBlock -> IO (Ptr Instruction)++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueBasicBlock.html#gaa0bb2c95802d06bf94f4c55e61fc3477>+foreign import ccall unsafe "LLVMGetLastInstruction" getLastInstruction ::+ Ptr BasicBlock -> IO (Ptr Instruction)++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueInstruction.html#ga1b4c3bd197e86e8bffdda247ddf8ec5e>+foreign import ccall unsafe "LLVMGetNextInstruction" getNextInstruction ::+ Ptr Instruction -> IO (Ptr Instruction)+
+ src/LLVM/Internal/FFI/BinaryOperator.h view
@@ -0,0 +1,16 @@+#ifndef __LLVM_INTERNAL_FFI__BINARY_OPERATOR__H__+#define __LLVM_INTERNAL_FFI__BINARY_OPERATOR__H__++#define LLVM_HS_FOR_EACH_POSSIBLY_EXACT_BINARY_OPERATOR(macro) \+ macro(UDiv) \+ macro(SDiv) \+ macro(LShr) \+ macro(AShr)++#define LLVM_HS_FOR_EACH_OVERFLOWING_BINARY_OPERATOR(macro) \+ macro(Add) \+ macro(Mul) \+ macro(Shl) \+ macro(Sub) \++#endif
+ src/LLVM/Internal/FFI/BinaryOperator.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE+ ForeignFunctionInterface,+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+-- | FFI functions for handling the LLVM BinaryOperator class+module LLVM.Internal.FFI.BinaryOperator where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.PtrHierarchy+import LLVM.Internal.FFI.LLVMCTypes++foreign import ccall unsafe "LLVMIsABinaryOperator" isABinaryOperator ::+ Ptr Value -> IO (Ptr BinaryOperator)++foreign import ccall unsafe "LLVM_Hs_HasNoSignedWrap" hasNoSignedWrap ::+ Ptr Value -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_HasNoUnsignedWrap" hasNoUnsignedWrap ::+ Ptr Value -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_IsExact" isExact ::+ Ptr Value -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_GetFastMathFlags" getFastMathFlags ::+ Ptr Value -> IO FastMathFlags
+ src/LLVM/Internal/FFI/Bitcode.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}++-- | Functions to read and write LLVM bitcode+module LLVM.Internal.FFI.Bitcode where++import LLVM.Prelude++import LLVM.Internal.FFI.Context+import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.MemoryBuffer+import LLVM.Internal.FFI.Module+import LLVM.Internal.FFI.PtrHierarchy++import Foreign.C+import Foreign.Ptr++foreign import ccall unsafe "LLVM_Hs_ParseBitcode" parseBitcode ::+ Ptr Context -> Ptr MemoryBuffer -> Ptr (OwnerTransfered CString) -> IO (Ptr Module)++foreign import ccall unsafe "LLVM_Hs_WriteBitcode" writeBitcode ::+ Ptr Module -> Ptr RawOStream -> IO ()++ +
+ src/LLVM/Internal/FFI/BitcodeC.cpp view
@@ -0,0 +1,34 @@+#define __STDC_LIMIT_MACROS+#include "llvm/IR/LLVMContext.h"+#include "llvm/IR/Module.h"+#include "llvm-c/Core.h"+#include "llvm/Support/raw_ostream.h"+#include "llvm/Support/MemoryBuffer.h"+#include "llvm/Bitcode/BitcodeReader.h"+#include "llvm/Bitcode/BitcodeWriter.h"++using namespace llvm;++extern "C" {++LLVMModuleRef LLVM_Hs_ParseBitcode(+ LLVMContextRef c,+ LLVMMemoryBufferRef mb, + char **error+) {+ Expected<std::unique_ptr<Module>> moduleOrErr = parseBitcodeFile(unwrap(mb)->getMemBufferRef(), *unwrap(c));+ if (Error err = moduleOrErr.takeError()) {+ handleAllErrors(std::move(err), [&](ErrorInfoBase &eib) {+ *error = strdup(eib.message().c_str());+ });+ return nullptr;+ }+ return wrap(moduleOrErr.get().release());+}++void LLVM_Hs_WriteBitcode(LLVMModuleRef m, raw_ostream &os) {+ WriteBitcodeToFile(unwrap(m), os);+}++}+
+ src/LLVM/Internal/FFI/Builder.hs view
@@ -0,0 +1,184 @@+{-#+ LANGUAGE+ ForeignFunctionInterface,+ TemplateHaskell,+ ViewPatterns+ #-}+-- | FFI glue for llvm::IRBuilder - llvm's IR construction state object+module LLVM.Internal.FFI.Builder where++import LLVM.Prelude++import qualified Language.Haskell.TH as TH++import Foreign.Ptr+import Foreign.C++import qualified Data.List as List+import qualified Data.Map as Map++import qualified LLVM.AST.Instruction as A+import LLVM.Internal.InstructionDefs as ID++import LLVM.Internal.FFI.Cleanup+import LLVM.Internal.FFI.Context+import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.PtrHierarchy++data Builder++foreign import ccall unsafe "LLVMCreateBuilderInContext" createBuilderInContext ::+ Ptr Context -> IO (Ptr Builder)++foreign import ccall unsafe "LLVMDisposeBuilder" disposeBuilder ::+ Ptr Builder -> IO ()++foreign import ccall unsafe "LLVMPositionBuilderAtEnd" positionBuilderAtEnd ::+ Ptr Builder -> Ptr BasicBlock -> IO ()+++foreign import ccall unsafe "LLVMBuildRet" buildRet ::+ Ptr Builder -> Ptr Value -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildBr" buildBr ::+ Ptr Builder -> Ptr BasicBlock -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildCondBr" buildCondBr ::+ Ptr Builder -> Ptr Value -> Ptr BasicBlock -> Ptr BasicBlock -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildSwitch" buildSwitch ::+ Ptr Builder -> Ptr Value -> Ptr BasicBlock -> CUInt -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildIndirectBr" buildIndirectBr ::+ Ptr Builder -> Ptr Value -> CUInt -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildInvoke" buildInvoke ::+ Ptr Builder -> Ptr Value -> Ptr (Ptr Value) -> CUInt+ -> Ptr BasicBlock -> Ptr BasicBlock -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildResume" buildResume ::+ Ptr Builder -> Ptr Value -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildUnreachable" buildUnreachable ::+ Ptr Builder -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVM_Hs_BuildCleanupRet" buildCleanupRet ::+ Ptr Builder -> Ptr Value -> Ptr BasicBlock -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVM_Hs_BuildCatchRet" buildCatchRet ::+ Ptr Builder -> Ptr Value -> Ptr BasicBlock -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVM_Hs_BuildCatchSwitch" buildCatchSwitch ::+ Ptr Builder -> Ptr Value -> Ptr BasicBlock -> CUInt -> IO (Ptr Instruction)++$(do+ liftM concat $ sequence $ do+ let instrInfo = ID.outerJoin ID.astInstructionRecs ID.instructionDefs+ (lrn, ii) <- Map.toList instrInfo+ (TH.RecC _ (unzip3 -> (_, _, fieldTypes)), ID.InstructionDef { ID.cAPIName = a, ID.instructionKind = k }) <- case ii of+ (Just r, Just d) -> return (r,d)+ (Just _, Nothing) -> error $ "An AST instruction was not found in the LLVM instruction defs"+ (Nothing, Just ID.InstructionDef { ID.instructionKind = k }) | k /= ID.Terminator ->+ error $ "LLVM instruction def " ++ lrn ++ " not found in the AST"+ _ -> []++ let ats = map typeMapping (fieldTypes List.\\ [TH.ConT ''A.InstructionMetadata, TH.ConT ''A.FastMathFlags])+ cName = (if hasFlags fieldTypes then "LLVM_Hs_" else "LLVM") ++ "Build" ++ a+ rt <- case k of+ ID.Binary -> [[t| BinaryOperator |]]+ ID.Cast -> [[t| Instruction |]]+ _ -> []+ return $ foreignDecl cName ("build" ++ a) ([[t| Ptr Builder |]] ++ ats ++ [[t| CString |]]) [t| Ptr $(rt) |]+ )++foreign import ccall unsafe "LLVMBuildArrayAlloca" buildAlloca ::+ Ptr Builder -> Ptr Type -> Ptr Value -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVM_Hs_BuildLoad" buildLoad' ::+ Ptr Builder -> LLVMBool -> Ptr Value -> MemoryOrdering -> SynchronizationScope -> CUInt -> CString -> IO (Ptr Instruction)++buildLoad :: Ptr Builder -> LLVMBool -> Ptr Value -> (SynchronizationScope, MemoryOrdering) -> CUInt -> CString -> IO (Ptr Instruction)+buildLoad builder vol a' (ss, mo) al s = buildLoad' builder vol a' mo ss al s++foreign import ccall unsafe "LLVM_Hs_BuildStore" buildStore' ::+ Ptr Builder -> LLVMBool -> Ptr Value -> Ptr Value -> MemoryOrdering -> SynchronizationScope -> CUInt -> CString -> IO (Ptr Instruction)++buildStore :: Ptr Builder -> LLVMBool -> Ptr Value -> Ptr Value -> (SynchronizationScope, MemoryOrdering) -> CUInt -> CString -> IO (Ptr Instruction)+buildStore builder vol a' v' (ss, mo) al s = buildStore' builder vol a' v' mo ss al s++foreign import ccall unsafe "LLVMBuildGEP" buildGetElementPtr' ::+ Ptr Builder -> Ptr Value -> Ptr (Ptr Value) -> CUInt -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildInBoundsGEP" buildInBoundsGetElementPtr' ::+ Ptr Builder -> Ptr Value -> Ptr (Ptr Value) -> CUInt -> CString -> IO (Ptr Instruction)++buildGetElementPtr :: Ptr Builder -> LLVMBool -> Ptr Value -> (CUInt, Ptr (Ptr Value)) -> CString -> IO (Ptr Instruction)+buildGetElementPtr builder (LLVMBool 1) a (n, is) s = buildInBoundsGetElementPtr' builder a is n s+buildGetElementPtr builder (LLVMBool 0) a (n, is) s = buildGetElementPtr' builder a is n s++foreign import ccall unsafe "LLVM_Hs_BuildFence" buildFence' ::+ Ptr Builder -> MemoryOrdering -> SynchronizationScope -> CString -> IO (Ptr Instruction)++buildFence :: Ptr Builder -> (SynchronizationScope, MemoryOrdering) -> CString -> IO (Ptr Instruction)+buildFence builder (ss, mo) s = buildFence' builder mo ss s++foreign import ccall unsafe "LLVM_Hs_BuildAtomicCmpXchg" buildCmpXchg' ::+ Ptr Builder -> LLVMBool -> Ptr Value -> Ptr Value -> Ptr Value -> MemoryOrdering -> MemoryOrdering -> SynchronizationScope -> CString -> IO (Ptr Instruction)++buildCmpXchg :: Ptr Builder -> LLVMBool -> Ptr Value -> Ptr Value -> Ptr Value -> (SynchronizationScope, MemoryOrdering) -> MemoryOrdering -> CString -> IO (Ptr Instruction)+buildCmpXchg builder vol a e r (ss, smo) fmo s = buildCmpXchg' builder vol a e r smo fmo ss s++foreign import ccall unsafe "LLVM_Hs_BuildAtomicRMW" buildAtomicRMW' ::+ Ptr Builder -> LLVMBool -> RMWOperation -> Ptr Value -> Ptr Value -> MemoryOrdering -> SynchronizationScope -> CString -> IO (Ptr Instruction)++buildAtomicRMW :: Ptr Builder -> LLVMBool -> RMWOperation -> Ptr Value -> Ptr Value -> (SynchronizationScope, MemoryOrdering) -> CString -> IO (Ptr Instruction)+buildAtomicRMW builder vol rmwOp a v (ss, mo) s = buildAtomicRMW' builder vol rmwOp a v mo ss s++foreign import ccall unsafe "LLVMBuildICmp" buildICmp ::+ Ptr Builder -> ICmpPredicate -> Ptr Value -> Ptr Value -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildFCmp" buildFCmp ::+ Ptr Builder -> FCmpPredicate -> Ptr Value -> Ptr Value -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildPhi" buildPhi ::+ Ptr Builder -> Ptr Type -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildCall" buildCall ::+ Ptr Builder -> Ptr Value -> Ptr (Ptr Value) -> CUInt -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildSelect" buildSelect ::+ Ptr Builder -> Ptr Value -> Ptr Value -> Ptr Value -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildVAArg" buildVAArg ::+ Ptr Builder -> Ptr Value -> Ptr Type -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildExtractElement" buildExtractElement ::+ Ptr Builder -> Ptr Value -> Ptr Value -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildInsertElement" buildInsertElement ::+ Ptr Builder -> Ptr Value -> Ptr Value -> Ptr Value -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildShuffleVector" buildShuffleVector ::+ Ptr Builder -> Ptr Value -> Ptr Value -> Ptr Constant -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVM_Hs_BuildExtractValue" buildExtractValue ::+ Ptr Builder -> Ptr Value -> Ptr CUInt -> CUInt -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVM_Hs_BuildInsertValue" buildInsertValue ::+ Ptr Builder -> Ptr Value -> Ptr Value -> Ptr CUInt -> CUInt -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVMBuildLandingPad" buildLandingPad' ::+ Ptr Builder -> Ptr Type -> Ptr Value -> CUInt -> CString -> IO (Ptr Instruction)++-- | The personality should be set via the function+buildLandingPad :: Ptr Builder -> Ptr Type -> CUInt -> CString -> IO (Ptr Instruction)+buildLandingPad builder ty numClauses name = buildLandingPad' builder ty nullPtr numClauses name++foreign import ccall unsafe "LLVM_Hs_BuildCleanupPad" buildCleanupPad ::+ Ptr Builder -> Ptr Value -> Ptr (Ptr Value) -> CUInt -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVM_Hs_BuildCatchPad" buildCatchPad ::+ Ptr Builder -> Ptr Value -> Ptr (Ptr Value) -> CUInt -> CString -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVM_Hs_SetFastMathFlags" setFastMathFlags ::+ Ptr Builder -> FastMathFlags -> IO ()
+ src/LLVM/Internal/FFI/BuilderC.cpp view
@@ -0,0 +1,223 @@+#define __STDC_LIMIT_MACROS+#include "llvm/IR/LLVMContext.h"+#include "llvm/IR/IRBuilder.h"++#include "llvm-c/Core.h"++#include "LLVM/Internal/FFI/Instruction.h"+#include "LLVM/Internal/FFI/BinaryOperator.h"++using namespace llvm;++namespace llvm {+static AtomicOrdering unwrap(LLVMAtomicOrdering l) {+ switch(l) {+#define ENUM_CASE(x) case LLVMAtomicOrdering ## x: return AtomicOrdering::x;+LLVM_HS_FOR_EACH_ATOMIC_ORDERING(ENUM_CASE)+#undef ENUM_CASE+ default: return AtomicOrdering(0);+ }+}++static SynchronizationScope unwrap(LLVMSynchronizationScope l) {+ switch(l) {+#define ENUM_CASE(x) case LLVM ## x ## SynchronizationScope: return x;+LLVM_HS_FOR_EACH_SYNCRONIZATION_SCOPE(ENUM_CASE)+#undef ENUM_CASE+ default: return SynchronizationScope(0);+ }+}+++static AtomicRMWInst::BinOp unwrap(LLVMAtomicRMWBinOp l) {+ switch(l) {+#define ENUM_CASE(x) case LLVMAtomicRMWBinOp ## x: return AtomicRMWInst::x;+LLVM_HS_FOR_EACH_RMW_OPERATION(ENUM_CASE)+#undef ENUM_CASE+ default: return AtomicRMWInst::BinOp(0);+ }+}++static FastMathFlags unwrap(LLVMFastMathFlags f) {+ FastMathFlags r = FastMathFlags();+#define ENUM_CASE(x,l) if (f & LLVM ## x) r.set ## x();+LLVM_HS_FOR_EACH_FAST_MATH_FLAG(ENUM_CASE)+#undef ENUM_CASE+ return r;+}++}++extern "C" {++#define ENUM_CASE(Op) \+LLVMValueRef LLVM_Hs_Build ## Op( \+ LLVMBuilderRef b, \+ LLVMBool nsw, \+ LLVMBool nuw, \+ LLVMValueRef o0, \+ LLVMValueRef o1, \+ const char *s \+) { \+ return wrap(unwrap(b)->Create ## Op(unwrap(o0), unwrap(o1), s, nuw, nsw)); \+}+LLVM_HS_FOR_EACH_OVERFLOWING_BINARY_OPERATOR(ENUM_CASE)+#undef ENUM_CASE++#define ENUM_CASE(Op) \+LLVMValueRef LLVM_Hs_Build ## Op( \+ LLVMBuilderRef b, \+ LLVMBool exact, \+ LLVMValueRef o0, \+ LLVMValueRef o1, \+ const char *s \+) { \+ return wrap(unwrap(b)->Create ## Op(unwrap(o0), unwrap(o1), s, exact)); \+}+LLVM_HS_FOR_EACH_POSSIBLY_EXACT_BINARY_OPERATOR(ENUM_CASE)+#undef ENUM_CASE++void LLVM_Hs_SetFastMathFlags(LLVMBuilderRef b, LLVMFastMathFlags f) {+ unwrap(b)->setFastMathFlags(unwrap(f));+}++LLVMValueRef LLVM_Hs_BuildLoad(+ LLVMBuilderRef b,+ LLVMBool isVolatile,+ LLVMValueRef p,+ LLVMAtomicOrdering atomicOrdering,+ LLVMSynchronizationScope synchScope,+ unsigned align,+ const char *name+) {+ LoadInst *i = unwrap(b)->CreateAlignedLoad(unwrap(p), align, isVolatile, name);+ i->setOrdering(unwrap(atomicOrdering));+ if (atomicOrdering != LLVMAtomicOrderingNotAtomic) i->setSynchScope(unwrap(synchScope));+ return wrap(i);+}++LLVMValueRef LLVM_Hs_BuildStore(+ LLVMBuilderRef b,+ LLVMBool isVolatile,+ LLVMValueRef p,+ LLVMValueRef v,+ LLVMAtomicOrdering atomicOrdering,+ LLVMSynchronizationScope synchScope,+ unsigned align,+ const char *name+) {+ StoreInst *i = unwrap(b)->CreateAlignedStore(unwrap(v), unwrap(p), align, isVolatile);+ i->setName(name);+ i->setOrdering(unwrap(atomicOrdering));+ if (atomicOrdering != LLVMAtomicOrderingNotAtomic) i->setSynchScope(unwrap(synchScope));+ return wrap(i);+}++LLVMValueRef LLVM_Hs_BuildFence(+ LLVMBuilderRef b, LLVMAtomicOrdering lao, LLVMSynchronizationScope lss, const char *name+) {+ FenceInst *i = unwrap(b)->CreateFence(unwrap(lao), unwrap(lss));+ i->setName(name);+ return wrap(i);+}++LLVMValueRef LLVM_Hs_BuildAtomicCmpXchg(+ LLVMBuilderRef b,+ LLVMBool v,+ LLVMValueRef ptr, + LLVMValueRef cmp, + LLVMValueRef n, + LLVMAtomicOrdering successOrdering,+ LLVMAtomicOrdering failureOrdering,+ LLVMSynchronizationScope lss,+ const char *name+) {+ AtomicCmpXchgInst *a = unwrap(b)->CreateAtomicCmpXchg(+ unwrap(ptr), unwrap(cmp), unwrap(n), unwrap(successOrdering), unwrap(failureOrdering), unwrap(lss)+ );+ a->setVolatile(v);+ a->setName(name);+ return wrap(a);+}++LLVMValueRef LLVM_Hs_BuildAtomicRMW(+ LLVMBuilderRef b,+ LLVMBool v,+ LLVMAtomicRMWBinOp rmwOp,+ LLVMValueRef ptr, + LLVMValueRef val, + LLVMAtomicOrdering lao,+ LLVMSynchronizationScope lss,+ const char *name+) {+ AtomicRMWInst *a = unwrap(b)->CreateAtomicRMW(+ unwrap(rmwOp), unwrap(ptr), unwrap(val), unwrap(lao), unwrap(lss)+ );+ a->setVolatile(v);+ a->setName(name);+ return wrap(a);+}++LLVMValueRef LLVM_Hs_BuildExtractValue(+ LLVMBuilderRef b,+ LLVMValueRef a,+ unsigned *idxs,+ unsigned n,+ const char *name+) {+ return wrap(unwrap(b)->CreateExtractValue(unwrap(a), ArrayRef<unsigned>(idxs, n), name));+}++LLVMValueRef LLVM_Hs_BuildInsertValue(+ LLVMBuilderRef b,+ LLVMValueRef a,+ LLVMValueRef v,+ unsigned *idxs,+ unsigned n,+ const char *name+) {+ return wrap(unwrap(b)->CreateInsertValue(unwrap(a), unwrap(v), ArrayRef<unsigned>(idxs, n), name));+}++LLVMValueRef LLVM_Hs_BuildCleanupPad(LLVMBuilderRef b, LLVMValueRef parentPad,+ LLVMValueRef *args, unsigned numArgs,+ const char *name) {+ return wrap(unwrap(b)->CreateCleanupPad(unwrap(parentPad),+ makeArrayRef(unwrap(args), numArgs),+ name));+}++LLVMValueRef LLVM_Hs_BuildCatchPad(LLVMBuilderRef b, LLVMValueRef catchSwitch,+ LLVMValueRef *args, unsigned numArgs,+ const char *name) {+ return wrap(unwrap(b)->CreateCatchPad(unwrap(catchSwitch),+ makeArrayRef(unwrap(args), numArgs),+ name));+}++LLVMValueRef LLVM_Hs_BuildCleanupRet(LLVMBuilderRef b, LLVMValueRef cleanupPad,+ LLVMBasicBlockRef unwindDest) {+ // Due to the way name resolution works in llvm-hs, cleanupPad might not+ // actually be a CleanupPadInst. However, it will later be replaced by one.+ // Pretending that we have one is thus ok here.+ auto cleanupPad_ = static_cast<CleanupPadInst*>(unwrap<Value>(cleanupPad));+ return wrap(unwrap(b)->CreateCleanupRet(cleanupPad_,+ unwrap(unwindDest)));+}++LLVMValueRef LLVM_Hs_BuildCatchRet(LLVMBuilderRef b, LLVMValueRef catchPad,+ LLVMBasicBlockRef successor) {+ // Due to the way name resolution works in llvm-hs, catchPad might not+ // actually be a CatchPadInst. However, it will later be replaced by one.+ // Pretending that we have one is thus ok here.+ auto catchPad_ = static_cast<CatchPadInst *>(unwrap<Value>(catchPad));+ return wrap(unwrap(b)->CreateCatchRet(catchPad_, unwrap(successor)));+}++LLVMValueRef LLVM_Hs_BuildCatchSwitch(LLVMBuilderRef b, LLVMValueRef parentPad,+ LLVMBasicBlockRef unwindDest,+ unsigned numHandlers) {+ return wrap(unwrap(b)->CreateCatchSwitch(unwrap(parentPad),+ unwrap(unwindDest), numHandlers));+}+}
+ src/LLVM/Internal/FFI/ByteRangeCallback.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}+module LLVM.Internal.FFI.ByteRangeCallback where++import LLVM.Prelude++import Foreign.C+import Foreign.Ptr++type ByteRangeCallback = Ptr CChar -> CSize -> IO ()+foreign import ccall "wrapper" wrapByteRangeCallback :: + ByteRangeCallback -> IO (FunPtr ByteRangeCallback)+
+ src/LLVM/Internal/FFI/CallingConvention.h view
@@ -0,0 +1,35 @@+#ifndef __LLVM_INTERNAL_FFI__CALLING_CONVENTION__H__+#define __LLVM_INTERNAL_FFI__CALLING_CONVENTION__H__++#define LLVM_HS_FOR_EACH_CALLING_CONVENTION(macro) \+ macro(C, 0) \+ macro(Fast, 8) \+ macro(Cold, 9) \+ macro(GHC, 10) \+ macro(HiPE, 11) \+ macro(WebKit_JS, 12) \+ macro(AnyReg, 13) \+ macro(PreserveMost, 14) \+ macro(PreserveAll, 15) \+ macro(X86_StdCall, 64) \+ macro(X86_FastCall, 65) \+ macro(ARM_APCS, 66) \+ macro(ARM_AAPCS, 67) \+ macro(ARM_AAPCS_VFP, 68) \+ macro(MSP430_INTR, 69) \+ macro(X86_ThisCall, 70) \+ macro(PTX_Kernel, 71) \+ macro(PTX_Device, 72) \+ macro(SPIR_FUNC, 75) \+ macro(SPIR_KERNEL, 76) \+ macro(Intel_OCL_BI, 77) \+ macro(X86_64_SysV, 78) \+ macro(X86_64_Win64, 79)++typedef enum {+#define ENUM_CASE(l,n) LLVM_Hs_CallingConvention_ ## l = n,+ LLVM_HS_FOR_EACH_CALLING_CONVENTION(ENUM_CASE)+#undef ENUM_CASE+} LLVM_Hs_CallingConvention;++#endif
+ src/LLVM/Internal/FFI/CallingConventionC.cpp view
@@ -0,0 +1,10 @@+#include "LLVM/Internal/FFI/CallingConvention.h"+#include "llvm/IR/CallingConv.h"++#define CHECK(l, n) \+ static_assert(unsigned(llvm::CallingConv::l) == \+ unsigned(LLVM_Hs_CallingConvention_##l), \+ "LLVM_Hs_CallingConvention enum out of sync w/ " \+ "llvm::CallingConv::ID for " #l);+LLVM_HS_FOR_EACH_CALLING_CONVENTION(CHECK)+#undef CHECK
+ src/LLVM/Internal/FFI/Cleanup.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE+ TemplateHaskell+ #-}+module LLVM.Internal.FFI.Cleanup where++import LLVM.Prelude++import Language.Haskell.TH+import Data.Sequence as Seq++import Foreign.C+import Foreign.Ptr++import LLVM.Internal.FFI.LLVMCTypes+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI++import qualified LLVM.AST.IntegerPredicate as A (IntegerPredicate) +import qualified LLVM.AST.FloatingPointPredicate as A (FloatingPointPredicate) +import qualified LLVM.AST.Constant as A.C (Constant)+import qualified LLVM.AST.Operand as A (Operand)+import qualified LLVM.AST.Type as A (Type)+import qualified LLVM.AST.Instruction as A (FastMathFlags)++foreignDecl :: String -> String -> [TypeQ] -> TypeQ -> DecsQ+foreignDecl cName hName argTypeQs returnTypeQ = do+ let foreignDecl' hName argTypeQs = + forImpD cCall unsafe cName (mkName hName) + (foldr (\a b -> appT (appT arrowT a) b) (appT (conT ''IO) returnTypeQ) argTypeQs)+ splitTuples :: [Type] -> Q ([Type], [Pat], [Exp])+ splitTuples ts = do+ let f :: Type -> Q (Seq Type, Pat, Seq Exp)+ f x@(AppT _ _) = maybe (d x) (\q -> q >>= \(ts, ps, es) -> return (ts, TupP (toList ps), es)) (g 0 x)+ f x = d x+ g :: Int -> Type -> Maybe (Q (Seq Type, Seq Pat, Seq Exp))+ g n (TupleT m) | m == n = return (return (Seq.empty, Seq.empty, Seq.empty))+ g n (AppT a b) = do+ k <- g (n+1) a+ return $ do+ (ts, ps, es) <- k+ (ts', p', es') <- f b+ return (ts >< ts', ps |> p', es >< es')+ g _ _ = Nothing+ d :: Type -> Q (Seq Type, Pat, Seq Exp)+ d x = do+ n <- newName "v"+ return (Seq.singleton x, VarP n, Seq.singleton (VarE n))+ seqsToList :: [Seq a] -> [a]+ seqsToList = toList . foldr (><) Seq.empty+ + (tss, ps, ess) <- liftM unzip3 . mapM f $ ts+ return (seqsToList tss, ps, seqsToList ess)++ + argTypes <- sequence argTypeQs+ (ts, ps, es) <- splitTuples argTypes+ let phName = hName ++ "'"+ sequence [+ foreignDecl' phName (map return ts),+ funD (mkName hName) [+ clause (map return ps) (normalB (foldl appE (varE (mkName phName)) (map return es))) []+ ]+ ]++-- | The LLVM C-API for instructions with boolean flags (e.g. nsw) and is weak, so they get+-- separated out for different handling. This check is an accurate but crude test for whether+-- an instruction needs such handling.+hasFlags :: [Type] -> Bool+hasFlags = any (== ConT ''Bool)++typeMapping :: Type -> TypeQ+typeMapping t = case t of+ ConT h | h == ''Bool -> [t| LLVMBool |]+ | h == ''Int32 -> [t| CInt |]+ | h == ''Word32 -> [t| CUInt |]+ | h == ''String -> [t| CString |]+ | h == ''A.Operand -> [t| Ptr FFI.Value |]+ | h == ''A.Type -> [t| Ptr FFI.Type |]+ | h == ''A.C.Constant -> [t| Ptr FFI.Constant |]+ | h == ''A.FloatingPointPredicate -> [t| FCmpPredicate |]+ | h == ''A.IntegerPredicate -> [t| ICmpPredicate |]+ | h == ''A.FastMathFlags -> [t| FastMathFlags |]+ AppT ListT x -> foldl1 appT [tupleT 2, [t| CUInt |], appT [t| Ptr |] (typeMapping x)]+ x -> error $ "type not handled in Cleanup typeMapping: " ++ show x
+ src/LLVM/Internal/FFI/CommandLine.hs view
@@ -0,0 +1,15 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}+module LLVM.Internal.FFI.CommandLine where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++foreign import ccall unsafe "LLVM_Hs_ParseCommandLineOptions" parseCommandLineOptions' ::+ CUInt -> Ptr (Ptr CChar) -> Ptr CChar -> IO ()++parseCommandLineOptions :: (CUInt, Ptr (Ptr CChar)) -> Ptr CChar -> IO ()+parseCommandLineOptions = uncurry parseCommandLineOptions'
+ src/LLVM/Internal/FFI/CommandLineC.cpp view
@@ -0,0 +1,12 @@+#define __STDC_LIMIT_MACROS+#include "llvm/Support/CommandLine.h"++using namespace llvm;++extern "C" {++void LLVM_Hs_ParseCommandLineOptions(unsigned argc, const char * const *argv, const char *overview) {+ cl::ParseCommandLineOptions(argc, argv, overview);+}++}
+ src/LLVM/Internal/FFI/Constant.h view
@@ -0,0 +1,20 @@+#ifndef __LLVM_INTERNAL_FFI__CONSTANT__H__+#define __LLVM_INTERNAL_FFI__CONSTANT__H__++#define LLVM_HS_FOR_EACH_FLOAT_SEMANTICS(macro) \+ macro(IEEEhalf) \+ macro(IEEEsingle) \+ macro(IEEEdouble) \+ macro(IEEEquad) \+ macro(PPCDoubleDouble) \+ macro(x87DoubleExtended) \+ macro(Bogus)++typedef enum {+#define ENUM_CASE(x) LLVMFloatSemantics ## x,+LLVM_HS_FOR_EACH_FLOAT_SEMANTICS(ENUM_CASE)+#undef ENUM_CASE+} LLVMFloatSemantics;+++#endif
+ src/LLVM/Internal/FFI/Constant.hs view
@@ -0,0 +1,145 @@+{-# LANGUAGE+ TemplateHaskell,+ ForeignFunctionInterface,+ MultiParamTypeClasses,+ UndecidableInstances,+ ViewPatterns+ #-}+-- | FFI functions for handling the LLVM Constant class+module LLVM.Internal.FFI.Constant where++import LLVM.Prelude++import qualified Language.Haskell.TH as TH+import qualified LLVM.Internal.InstructionDefs as ID++import qualified Data.Map as Map++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.PtrHierarchy+import LLVM.Internal.FFI.Context+import LLVM.Internal.FFI.Cleanup+import LLVM.Internal.FFI.LLVMCTypes++foreign import ccall unsafe "LLVMIsConstant" isConstant ::+ Ptr Value -> IO (CUInt)++foreign import ccall unsafe "LLVMIsAConstant" isAConstant ::+ Ptr Value -> IO (Ptr Constant)++foreign import ccall unsafe "LLVMIsAConstantInt" isAConstantInt ::+ Ptr Value -> IO (Ptr Constant)++foreign import ccall unsafe "LLVMGetOperand" getConstantOperand ::+ Ptr Constant -> CUInt -> IO (Ptr Constant)++foreign import ccall unsafe "LLVMIsAConstantPointerNull" isAConstantPointerNull ::+ Ptr Value -> IO (Ptr Constant)++foreign import ccall unsafe "LLVM_Hs_GetConstantIntWords" getConstantIntWords ::+ Ptr Constant -> Ptr CUInt -> IO (Ptr Word64)++foreign import ccall unsafe "LLVM_Hs_ConstFloatDoubleValue" constFloatDoubleValue ::+ Ptr Constant -> IO CDouble++foreign import ccall unsafe "LLVM_Hs_ConstFloatFloatValue" constFloatFloatValue ::+ Ptr Constant -> IO CFloat++foreign import ccall unsafe "LLVMConstStructInContext" constStructInContext' ::+ Ptr Context -> Ptr (Ptr Constant) -> CUInt -> LLVMBool -> IO (Ptr Constant)++constStructInContext :: Ptr Context -> (CUInt, Ptr (Ptr Constant)) -> LLVMBool -> IO (Ptr Constant)+constStructInContext ctx (n, cs) p = constStructInContext' ctx cs n p++foreign import ccall unsafe "LLVMConstNamedStruct" constNamedStruct' ::+ Ptr Type -> Ptr (Ptr Constant) -> CUInt -> IO (Ptr Constant)++constNamedStruct :: Ptr Type -> (CUInt, Ptr (Ptr Constant)) -> IO (Ptr Constant)+constNamedStruct ty (n, cs) = constNamedStruct' ty cs n++foreign import ccall unsafe "LLVM_Hs_GetConstantDataSequentialElementAsConstant" getConstantDataSequentialElementAsConstant ::+ Ptr Constant -> CUInt -> IO (Ptr Constant)++foreign import ccall unsafe "LLVMConstIntOfArbitraryPrecision" constantIntOfArbitraryPrecision' ::+ Ptr Type -> CUInt -> Ptr Word64 -> IO (Ptr Constant)++constantIntOfArbitraryPrecision :: Ptr Type -> (CUInt, Ptr Word64) -> IO (Ptr Constant)+constantIntOfArbitraryPrecision t = uncurry (constantIntOfArbitraryPrecision' t)++foreign import ccall unsafe "LLVM_Hs_ConstFloatOfArbitraryPrecision" constantFloatOfArbitraryPrecision ::+ Ptr Context -> CUInt -> Ptr Word64 -> FloatSemantics -> IO (Ptr Constant)++foreign import ccall unsafe "LLVM_Hs_GetConstantFloatWords" getConstantFloatWords ::+ Ptr Constant -> Ptr Word64 -> IO ()++foreign import ccall unsafe "LLVMConstVector" constantVector' ::+ Ptr (Ptr Constant) -> CUInt -> IO (Ptr Constant)++constantVector :: (CUInt, Ptr (Ptr Constant)) -> IO (Ptr Constant)+constantVector (n, cs) = constantVector' cs n++foreign import ccall unsafe "LLVMConstNull" constantNull ::+ Ptr Type -> IO (Ptr Constant)++foreign import ccall unsafe "LLVMConstArray" constantArray' ::+ Ptr Type -> Ptr (Ptr Constant) -> CUInt -> IO (Ptr Constant)++constantArray :: Ptr Type -> (CUInt, Ptr (Ptr Constant)) -> IO (Ptr Constant)+constantArray t (n, cs) = constantArray' t cs n++foreign import ccall unsafe "LLVM_Hs_ConstCast" constantCast ::+ CPPOpcode -> Ptr Constant -> Ptr Type -> IO (Ptr Constant)++foreign import ccall unsafe "LLVM_Hs_ConstBinaryOperator" constantBinaryOperator ::+ CPPOpcode -> Ptr Constant -> Ptr Constant -> IO (Ptr Constant)++$(do+ let constExprInfo = ID.innerJoin (ID.innerJoin ID.astConstantRecs ID.astInstructionRecs) ID.instructionDefs+ liftM concat $ sequence $ do+ (name, ((TH.RecC _ (unzip3 -> (_, _, fieldTypes)),_), ID.InstructionDef { ID.instructionKind = ik })) <- Map.toList constExprInfo+ prefix <- case ik of+ ID.Other -> return "LLVM"+ ID.Binary | hasFlags fieldTypes -> return "LLVM_Hs_"+ _ -> []+ return $+ foreignDecl (prefix ++ "Const" ++ name) ("constant" ++ name) (map typeMapping fieldTypes) [t| Ptr Constant |]+ )++foreign import ccall unsafe "LLVMConstGEP" constantGetElementPtr' ::+ Ptr Constant -> Ptr (Ptr Constant) -> CUInt -> IO (Ptr Constant)++foreign import ccall unsafe "LLVMConstInBoundsGEP" constantInBoundsGetElementPtr' ::+ Ptr Constant -> Ptr (Ptr Constant) -> CUInt -> IO (Ptr Constant)++constantGetElementPtr :: LLVMBool -> Ptr Constant -> (CUInt, Ptr (Ptr Constant)) -> IO (Ptr Constant)+constantGetElementPtr (LLVMBool ib) a (n, is) =+ (case ib of { 0 -> constantGetElementPtr'; 1 -> constantInBoundsGetElementPtr' }) a is n++foreign import ccall unsafe "LLVM_Hs_GetConstCPPOpcode" getConstantCPPOpcode ::+ Ptr Constant -> IO CPPOpcode++foreign import ccall unsafe "LLVM_Hs_GetConstPredicate" getConstantICmpPredicate ::+ Ptr Constant -> IO ICmpPredicate++foreign import ccall unsafe "LLVM_Hs_GetConstPredicate" getConstantFCmpPredicate ::+ Ptr Constant -> IO FCmpPredicate++foreign import ccall unsafe "LLVM_Hs_GetConstIndices" getConstantIndices ::+ Ptr Constant -> Ptr CUInt -> IO (Ptr CUInt)++foreign import ccall unsafe "LLVMGetUndef" constantUndef ::+ Ptr Type -> IO (Ptr Constant)++foreign import ccall unsafe "LLVMBlockAddress" blockAddress ::+ Ptr Value -> Ptr BasicBlock -> IO (Ptr Constant)++foreign import ccall unsafe "LLVM_Hs_GetBlockAddressFunction" getBlockAddressFunction ::+ Ptr Constant -> IO (Ptr Value)++foreign import ccall unsafe "LLVM_Hs_GetBlockAddressBlock" getBlockAddressBlock ::+ Ptr Constant -> IO (Ptr BasicBlock)++foreign import ccall unsafe "LLVM_Hs_GetConstTokenNone" getConstTokenNone ::+ Ptr Context -> IO (Ptr Constant)
+ src/LLVM/Internal/FFI/ConstantC.cpp view
@@ -0,0 +1,114 @@+#define __STDC_LIMIT_MACROS+#include "llvm/IR/LLVMContext.h"+#include "llvm/IR/Constants.h"+#include "llvm/IR/Function.h"++#include "llvm-c/Core.h"+#include "LLVM/Internal/FFI/Value.h"+#include "LLVM/Internal/FFI/Constant.h"+#include "LLVM/Internal/FFI/BinaryOperator.h"++using namespace llvm;++namespace llvm {++static const struct fltSemantics &unwrap(LLVMFloatSemantics s) {+ switch(s) {+#define ENUM_CASE(x) case LLVMFloatSemantics ## x: return APFloat::x();+LLVM_HS_FOR_EACH_FLOAT_SEMANTICS(ENUM_CASE)+#undef ENUM_CASE+ default: return APFloat::Bogus();+ }+}++}++extern "C" {++LLVMValueRef LLVM_Hs_GetConstantDataSequentialElementAsConstant(LLVMValueRef v, unsigned i) {+ return wrap(unwrap<ConstantDataSequential>(v)->getElementAsConstant(i));+}++LLVMValueRef LLVM_Hs_GetBlockAddressFunction(LLVMValueRef v) {+ return wrap(unwrap<BlockAddress>(v)->getFunction());+}++LLVMBasicBlockRef LLVM_Hs_GetBlockAddressBlock(LLVMValueRef v) {+ return wrap(unwrap<BlockAddress>(v)->getBasicBlock());+}++double LLVM_Hs_ConstFloatDoubleValue(LLVMValueRef v) {+ return unwrap<ConstantFP>(v)->getValueAPF().convertToDouble();+}++float LLVM_Hs_ConstFloatFloatValue(LLVMValueRef v) {+ return unwrap<ConstantFP>(v)->getValueAPF().convertToFloat();+}++LLVMValueRef LLVM_Hs_ConstCast(unsigned opcode, LLVMValueRef v, LLVMTypeRef t) {+ return wrap(ConstantExpr::getCast(opcode, unwrap<Constant>(v), unwrap(t)));+}++LLVMValueRef LLVM_Hs_ConstBinaryOperator(unsigned opcode, LLVMValueRef o0, LLVMValueRef o1) {+ return wrap(ConstantExpr::get(opcode, unwrap<Constant>(o0), unwrap<Constant>(o1)));+}++#define CASE_CODE(op) \+LLVMValueRef LLVM_Hs_Const ## op(unsigned nsw, unsigned nuw, LLVMValueRef o0, LLVMValueRef o1) { \+ return wrap(ConstantExpr::get ## op(unwrap<Constant>(o0), unwrap<Constant>(o1), nuw != 0, nsw != 0)); \+}+LLVM_HS_FOR_EACH_OVERFLOWING_BINARY_OPERATOR(CASE_CODE)+#undef CASE_CODE++#define CASE_CODE(op) \+LLVMValueRef LLVM_Hs_Const ## op(unsigned isExact, LLVMValueRef o0, LLVMValueRef o1) { \+ return wrap(ConstantExpr::get ## op(unwrap<Constant>(o0), unwrap<Constant>(o1), isExact != 0)); \+}+LLVM_HS_FOR_EACH_POSSIBLY_EXACT_BINARY_OPERATOR(CASE_CODE)+#undef CASE_CODE++unsigned LLVM_Hs_GetConstCPPOpcode(LLVMValueRef v) {+ return unwrap<ConstantExpr>(v)->getOpcode();+}++unsigned LLVM_Hs_GetConstPredicate(LLVMValueRef v) {+ return unwrap<ConstantExpr>(v)->getPredicate();+}++const unsigned *LLVM_Hs_GetConstIndices(LLVMValueRef v, unsigned *n) {+ ArrayRef<unsigned> r = unwrap<ConstantExpr>(v)->getIndices();+ *n = r.size();+ return r.data();+}++const uint64_t *LLVM_Hs_GetConstantIntWords(LLVMValueRef v, unsigned *n) {+ const APInt &i = unwrap<ConstantInt>(v)->getValue();+ *n = i.getNumWords();+ return i.getRawData();+}++LLVMValueRef LLVM_Hs_ConstFloatOfArbitraryPrecision(+ LLVMContextRef c,+ unsigned bits,+ const uint64_t *words,+ LLVMFloatSemantics semantics+) {+ return wrap(+ ConstantFP::get(+ *unwrap(c),+ APFloat(unwrap(semantics), APInt(bits, ArrayRef<uint64_t>(words, (bits-1)/64 + 1)))+ )+ );+}++void LLVM_Hs_GetConstantFloatWords(LLVMValueRef v, uint64_t *bits) {+ APInt a = unwrap<ConstantFP>(v)->getValueAPF().bitcastToAPInt();+ for(unsigned i=0; i != a.getNumWords(); ++i) bits[i] = a.getRawData()[i];+}++LLVMValueRef LLVM_Hs_GetConstTokenNone(LLVMContextRef context) {+ return wrap(ConstantTokenNone::get(*unwrap(context)));+}+++}
+ src/LLVM/Internal/FFI/Context.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}++-- | Functions for handling the LLVMContext class. In all other LLVM interfaces,+-- | prefer the newer explicitly thread-aware variants which use contexts+-- | over corresponding older variants which implicitly reference a global context.+-- | This choice allows multiple threads to do independent work with LLVM safely.+module LLVM.Internal.FFI.Context where++import LLVM.Prelude++import Foreign.Ptr++-- | a blind type to correspond to LLVMContext+data Context++-- | <http://llvm.org/doxygen/group__LLVMCCoreContext.html#gaac4f39a2d0b9735e64ac7681ab543b4c>+foreign import ccall unsafe "LLVMContextCreate" contextCreate ::+ IO (Ptr Context)++-- | <http://llvm.org/doxygen/group__LLVMCCoreContext.html#ga0055cde9a9b2497b332d639d8844a810>+foreign import ccall unsafe "LLVMGetGlobalContext" getGlobalContext ::+ IO (Ptr Context)++-- | <http://llvm.org/doxygen/group__LLVMCCoreContext.html#ga9cf8b0fb4a546d4cdb6f64b8055f5f57>+foreign import ccall unsafe "LLVMContextDispose" contextDispose ::+ Ptr Context -> IO ()
+ src/LLVM/Internal/FFI/DataLayout.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}++module LLVM.Internal.FFI.DataLayout where++import LLVM.Prelude++import Foreign.C.String+import Foreign.Ptr++import LLVM.Internal.FFI.LLVMCTypes++data DataLayout++-- Oooh those wacky LLVM C-API coders: C API called DataLayout TargetData.+-- Great. Just great.++foreign import ccall unsafe "LLVMCreateTargetData" createDataLayout :: + CString -> IO (Ptr DataLayout)++foreign import ccall unsafe "LLVMDisposeTargetData" disposeDataLayout :: + Ptr DataLayout -> IO ()++foreign import ccall unsafe "LLVMCopyStringRepOfTargetData" dataLayoutToString ::+ Ptr DataLayout -> IO (OwnerTransfered CString)
+ src/LLVM/Internal/FFI/ExecutionEngine.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}++module LLVM.Internal.FFI.ExecutionEngine where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.PtrHierarchy+import LLVM.Internal.FFI.Module+import LLVM.Internal.FFI.LLVMCTypes++data ExecutionEngine++foreign import ccall unsafe "LLVMCreateExecutionEngineForModule" createExecutionEngineForModule ::+ Ptr (Ptr ExecutionEngine) -> Ptr Module -> Ptr (OwnerTransfered CString) -> IO CUInt++foreign import ccall unsafe "LLVMCreateInterpreterForModule" createInterpreterForModule ::+ Ptr (Ptr ExecutionEngine) -> Ptr Module -> Ptr (OwnerTransfered CString) -> IO CUInt++foreign import ccall unsafe "LLVMCreateJITCompilerForModule" createJITCompilerForModule ::+ Ptr (Ptr ExecutionEngine) -> Ptr Module -> CUInt -> Ptr (OwnerTransfered CString) -> IO CUInt++foreign import ccall unsafe "LLVMCreateMCJITCompilerForModule" createMCJITCompilerForModule ::+ Ptr (Ptr ExecutionEngine) -> Ptr Module -> Ptr MCJITCompilerOptions -> CSize -> Ptr (OwnerTransfered CString) -> IO CUInt++foreign import ccall unsafe "LLVMDisposeExecutionEngine" disposeExecutionEngine ::+ Ptr ExecutionEngine -> IO ()++foreign import ccall unsafe "LLVMAddModule" addModule ::+ Ptr ExecutionEngine -> Ptr Module -> IO ()++foreign import ccall unsafe "LLVMRemoveModule" removeModule ::+ Ptr ExecutionEngine -> Ptr Module -> Ptr (Ptr Module) -> Ptr CString -> IO CUInt++foreign import ccall unsafe "LLVMFindFunction" findFunction ::+ Ptr ExecutionEngine -> CString -> Ptr (Ptr Function) -> IO CUInt++foreign import ccall unsafe "LLVMGetPointerToGlobal" getPointerToGlobal ::+ Ptr ExecutionEngine -> Ptr GlobalValue -> IO (Ptr ())++foreign import ccall unsafe "LLVMLinkInInterpreter" linkInInterpreter :: + IO ()++foreign import ccall unsafe "LLVMLinkInMCJIT" linkInMCJIT :: + IO ()++data MCJITCompilerOptions++foreign import ccall unsafe "LLVM_Hs_GetMCJITCompilerOptionsSize" getMCJITCompilerOptionsSize ::+ IO CSize++foreign import ccall unsafe "LLVMInitializeMCJITCompilerOptions" initializeMCJITCompilerOptions ::+ Ptr MCJITCompilerOptions -> CSize -> IO ()++foreign import ccall unsafe "LLVM_Hs_SetMCJITCompilerOptionsOptLevel" setMCJITCompilerOptionsOptLevel ::+ Ptr MCJITCompilerOptions -> CUInt -> IO ()++foreign import ccall unsafe "LLVM_Hs_SetMCJITCompilerOptionsCodeModel" setMCJITCompilerOptionsCodeModel ::+ Ptr MCJITCompilerOptions -> CodeModel -> IO ()++foreign import ccall unsafe "LLVM_Hs_SetMCJITCompilerOptionsNoFramePointerElim" setMCJITCompilerOptionsNoFramePointerElim ::+ Ptr MCJITCompilerOptions -> LLVMBool -> IO ()++foreign import ccall unsafe "LLVM_Hs_SetMCJITCompilerOptionsEnableFastISel" setMCJITCompilerOptionsEnableFastISel ::+ Ptr MCJITCompilerOptions -> LLVMBool -> IO ()++
+ src/LLVM/Internal/FFI/ExecutionEngineC.cpp view
@@ -0,0 +1,30 @@+#define __STDC_LIMIT_MACROS+#include "llvm/IR/LLVMContext.h"+#include "llvm-c/ExecutionEngine.h"++using namespace llvm;++extern "C" {++size_t LLVM_Hs_GetMCJITCompilerOptionsSize() {+ return sizeof(struct LLVMMCJITCompilerOptions);+}++void LLVM_Hs_SetMCJITCompilerOptionsOptLevel(struct LLVMMCJITCompilerOptions *o, unsigned x) {+ o->OptLevel = x;+}++void LLVM_Hs_SetMCJITCompilerOptionsCodeModel(struct LLVMMCJITCompilerOptions *o, LLVMCodeModel x) {+ o->CodeModel = x;+}++void LLVM_Hs_SetMCJITCompilerOptionsNoFramePointerElim(struct LLVMMCJITCompilerOptions *o, LLVMBool x) {+ o->NoFramePointerElim = x;+}++void LLVM_Hs_SetMCJITCompilerOptionsEnableFastISel(struct LLVMMCJITCompilerOptions *o, LLVMBool x) {+ o->EnableFastISel = x;+}++}+
+ src/LLVM/Internal/FFI/Function.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE+ ForeignFunctionInterface,+ MultiParamTypeClasses+ #-}++module LLVM.Internal.FFI.Function where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.Attribute+import LLVM.Internal.FFI.Context+import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.PtrHierarchy++foreign import ccall unsafe "LLVMGetFunctionCallConv" getFunctionCallingConvention ::+ Ptr Function -> IO CallingConvention++foreign import ccall unsafe "LLVMSetFunctionCallConv" setFunctionCallingConvention ::+ Ptr Function -> CallingConvention -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetFunctionMixedAttributeSet" getMixedAttributeSet ::+ Ptr Function -> IO MixedAttributeSet++foreign import ccall unsafe "LLVM_Hs_SetFunctionMixedAttributeSet" setMixedAttributeSet ::+ Ptr Function -> MixedAttributeSet -> IO ()++foreign import ccall unsafe "LLVMGetFirstBasicBlock" getFirstBasicBlock ::+ Ptr Function -> IO (Ptr BasicBlock)++foreign import ccall unsafe "LLVMGetLastBasicBlock" getLastBasicBlock ::+ Ptr Function -> IO (Ptr BasicBlock)++foreign import ccall unsafe "LLVMGetNextBasicBlock" getNextBasicBlock ::+ Ptr BasicBlock -> IO (Ptr BasicBlock)++foreign import ccall unsafe "LLVMAppendBasicBlockInContext" appendBasicBlockInContext ::+ Ptr Context -> Ptr Function -> CString -> IO (Ptr BasicBlock)+++foreign import ccall unsafe "LLVMCountParams" countParams ::+ Ptr Function -> IO CUInt++foreign import ccall unsafe "LLVMGetParams" getParams ::+ Ptr Function -> Ptr (Ptr Parameter) -> IO ()++foreign import ccall unsafe "LLVMGetGC" getGC ::+ Ptr Function -> IO CString++foreign import ccall unsafe "LLVMSetGC" setGC ::+ Ptr Function -> CString -> IO ()+++foreign import ccall unsafe "LLVM_Hs_HasFunctionPrefixData" hasPrefixData ::+ Ptr Function -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_GetFunctionPrefixData" getPrefixData ::+ Ptr Function -> IO (Ptr Constant)++foreign import ccall unsafe "LLVM_Hs_SetFunctionPrefixData" setPrefixData ::+ Ptr Function -> Ptr Constant -> IO ()++foreign import ccall unsafe "LLVMHasPersonalityFn" hasPersonalityFn ::+ Ptr Function -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_SetPersonalityFn" setPersonalityFn ::+ Ptr Function -> Ptr Constant -> IO ()++foreign import ccall unsafe "LLVMGetPersonalityFn" getPersonalityFn ::+ Ptr Function -> IO (Ptr Constant)
+ src/LLVM/Internal/FFI/FunctionC.cpp view
@@ -0,0 +1,41 @@+#define __STDC_LIMIT_MACROS+#include "llvm/IR/LLVMContext.h"+#include "llvm/IR/Attributes.h"+#include "llvm/IR/Function.h"+#include "llvm/IR/Value.h"++#include "llvm-c/Core.h"+#include "LLVM/Internal/FFI/AttributeC.hpp"++using namespace llvm;++extern "C" {++const AttributeSetImpl *LLVM_Hs_GetFunctionMixedAttributeSet(LLVMValueRef f) {+ return wrap(unwrap<Function>(f)->getAttributes());+}++void LLVM_Hs_SetFunctionMixedAttributeSet(LLVMValueRef f, AttributeSetImpl *asi) {+ unwrap<Function>(f)->setAttributes(unwrap(asi));+}++LLVMBool LLVM_Hs_HasFunctionPrefixData(LLVMValueRef f) {+ return unwrap<Function>(f)->hasPrefixData();+}++LLVMValueRef LLVM_Hs_GetFunctionPrefixData(LLVMValueRef f) {+ return wrap(unwrap<Function>(f)->getPrefixData());+}++void LLVM_Hs_SetFunctionPrefixData(LLVMValueRef f, LLVMValueRef p) {+ unwrap<Function>(f)->setPrefixData(unwrap<Constant>(p));+}++// This wrapper is necessary because LLVMSetPersonalityFn fails if+// personalityFn is a nullptr even though the C++ API allows that.+void LLVM_Hs_SetPersonalityFn(LLVMValueRef fn, LLVMValueRef personalityFn) {+ unwrap<Function>(fn)->setPersonalityFn(personalityFn == nullptr ?+ nullptr : unwrap<Constant>(personalityFn));+}++}
+ src/LLVM/Internal/FFI/GlobalAlias.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE+ ForeignFunctionInterface,+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+-- | FFI functions for handling the LLVM GlobalAlias class+module LLVM.Internal.FFI.GlobalAlias where++import LLVM.Prelude++import Foreign.Ptr++import LLVM.Internal.FFI.PtrHierarchy++-- | test if a 'Value' is a 'GlobalAlias'+foreign import ccall unsafe "LLVMIsAGlobalAlias" isAGlobalAlias ::+ Ptr Value -> IO (Ptr GlobalAlias)++-- | get the constant aliased by this alias+foreign import ccall unsafe "LLVM_Hs_GetAliasee" getAliasee ::+ Ptr GlobalAlias -> IO (Ptr Constant)++-- | set the constant aliased by this alias+foreign import ccall unsafe "LLVM_Hs_SetAliasee" setAliasee ::+ Ptr GlobalAlias -> Ptr Constant -> IO ()+
+ src/LLVM/Internal/FFI/GlobalAliasC.cpp view
@@ -0,0 +1,22 @@+#define __STDC_LIMIT_MACROS+#include "llvm/IR/LLVMContext.h"+#include "llvm/IR/GlobalAlias.h"+#include "llvm/IR/GlobalObject.h"++#include "llvm-c/Core.h"++#include <iostream>++using namespace llvm;++extern "C" {++LLVMValueRef LLVM_Hs_GetAliasee(LLVMValueRef g) {+ return wrap(unwrap<GlobalAlias>(g)->getAliasee());+}++void LLVM_Hs_SetAliasee(LLVMValueRef g, LLVMValueRef c) {+ unwrap<GlobalAlias>(g)->setAliasee(unwrap<Constant>(c));+}++}
+ src/LLVM/Internal/FFI/GlobalValue.h view
@@ -0,0 +1,58 @@+#ifndef __LLVM_INTERNAL_FFI__GLOBAL_VALUE__H__+#define __LLVM_INTERNAL_FFI__GLOBAL_VALUE__H__++#define LLVM_HS_FOR_EACH_LINKAGE(macro) \+ macro(External) \+ macro(AvailableExternally) \+ macro(LinkOnceAny) \+ macro(LinkOnceODR) \+ macro(WeakAny) \+ macro(WeakODR) \+ macro(Appending) \+ macro(Internal) \+ macro(Private) \+ macro(ExternalWeak) \+ macro(Common)++#define LLVM_HS_FOR_EACH_VISIBILITY(macro) \+ macro(Default) \+ macro(Hidden) \+ macro(Protected) \++#define LLVM_HS_FOR_EACH_COMDAT_SELECTION_KIND(macro) \+ macro(Any) \+ macro(ExactMatch) \+ macro(Largest) \+ macro(NoDuplicates) \+ macro(SameSize)++typedef enum {+#define ENUM_CASE(n) LLVM_Hs_COMDAT_Selection_Kind_ ## n,+LLVM_HS_FOR_EACH_COMDAT_SELECTION_KIND(ENUM_CASE)+#undef ENUM_CASE+} LLVM_Hs_COMDAT_Selection_Kind;++#define LLVM_HS_FOR_EACH_DLL_STORAGE_CLASS(macro) \+ macro(Default) \+ macro(DLLImport) \+ macro(DLLExport)++#define LLVM_HS_FOR_EACH_THREAD_LOCAL_MODE(macro) \+ macro(NotThreadLocal) \+ macro(GeneralDynamicTLSModel) \+ macro(LocalDynamicTLSModel) \+ macro(InitialExecTLSModel) \+ macro(LocalExecTLSModel)++#define LLVM_HS_FOR_EACH_UNNAMED_ADDR(macro) \+ macro(None) \+ macro(Local) \+ macro(Global)++typedef enum {+#define ENUM_CASE(x) LLVMUnnamedAddr ## x,+LLVM_HS_FOR_EACH_UNNAMED_ADDR(ENUM_CASE)+#undef ENUM_CASE+} LLVMUnnamedAddr;++#endif
+ src/LLVM/Internal/FFI/GlobalValue.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE+ ForeignFunctionInterface,+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+-- | FFI functions for handling the LLVM GlobalValue class+module LLVM.Internal.FFI.GlobalValue where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.PtrHierarchy+import LLVM.Internal.FFI.LLVMCTypes++data COMDAT++foreign import ccall unsafe "LLVMIsAGlobalValue" isAGlobalValue ::+ Ptr Value -> IO (Ptr GlobalValue)++foreign import ccall unsafe "LLVMGetLinkage" getLinkage ::+ Ptr GlobalValue -> IO Linkage++foreign import ccall unsafe "LLVMSetLinkage" setLinkage ::+ Ptr GlobalValue -> Linkage -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetSection" getSection ::+ Ptr GlobalValue -> Ptr CSize -> IO CString++foreign import ccall unsafe "LLVMSetSection" setSection ::+ Ptr GlobalValue -> CString -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetCOMDAT" getCOMDAT ::+ Ptr GlobalValue -> IO (Ptr COMDAT)++foreign import ccall unsafe "LLVM_Hs_SetCOMDAT" setCOMDAT ::+ Ptr GlobalObject -> Ptr COMDAT -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetCOMDATName" getCOMDATName ::+ Ptr COMDAT -> Ptr CSize -> IO (Ptr CChar)++foreign import ccall unsafe "LLVM_Hs_GetCOMDATSelectionKind" getCOMDATSelectionKind ::+ Ptr COMDAT -> IO COMDATSelectionKind++foreign import ccall unsafe "LLVM_Hs_SetCOMDATSelectionKind" setCOMDATSelectionKind ::+ Ptr COMDAT -> COMDATSelectionKind -> IO ()++foreign import ccall unsafe "LLVMGetVisibility" getVisibility ::+ Ptr GlobalValue -> IO Visibility++foreign import ccall unsafe "LLVMSetVisibility" setVisibility ::+ Ptr GlobalValue -> Visibility -> IO ()++foreign import ccall unsafe "LLVMGetDLLStorageClass" getDLLStorageClass ::+ Ptr GlobalValue -> IO DLLStorageClass++foreign import ccall unsafe "LLVMSetDLLStorageClass" setDLLStorageClass ::+ Ptr GlobalValue -> DLLStorageClass -> IO ()++foreign import ccall unsafe "LLVMGetAlignment" getAlignment ::+ Ptr GlobalValue -> IO CUInt++foreign import ccall unsafe "LLVMSetAlignment" setAlignment ::+ Ptr GlobalValue -> CUInt -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetUnnamedAddr" getUnnamedAddr ::+ Ptr GlobalValue -> IO UnnamedAddr++foreign import ccall unsafe "LLVM_Hs_SetUnnamedAddr" setUnnamedAddr ::+ Ptr GlobalValue -> UnnamedAddr -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetThreadLocalMode" getThreadLocalMode ::+ Ptr GlobalValue -> IO ThreadLocalMode++foreign import ccall unsafe "LLVM_Hs_SetThreadLocalMode" setThreadLocalMode ::+ Ptr GlobalValue -> ThreadLocalMode -> IO ()++
+ src/LLVM/Internal/FFI/GlobalValueC.cpp view
@@ -0,0 +1,87 @@+#define __STDC_LIMIT_MACROS+#include "llvm/IR/Comdat.h"+#include "llvm/IR/GlobalValue.h"+#include "llvm/IR/GlobalObject.h"+#include "llvm-c/Core.h"+#include "LLVM/Internal/FFI/GlobalValue.h"++using namespace llvm;++extern "C" {++const Comdat *LLVM_Hs_GetCOMDAT(LLVMValueRef globalVal) {+ return unwrap<GlobalValue>(globalVal)->getComdat();+}++void LLVM_Hs_SetCOMDAT(LLVMValueRef globalObj, Comdat *comdat) {+ return unwrap<GlobalObject>(globalObj)->setComdat(comdat);+}++const char *LLVM_Hs_GetCOMDATName(const Comdat &comdat, size_t &size) {+ StringRef ref = comdat.getName();+ size = ref.size();+ return ref.data();+}++#define ENUM_CASE(n) \+ static_assert(unsigned(Comdat::n) == \+ unsigned(LLVM_Hs_COMDAT_Selection_Kind_##n), \+ "COMDAT SelectionKind Enum mismatch");+LLVM_HS_FOR_EACH_COMDAT_SELECTION_KIND(ENUM_CASE)+#undef ENUM_CASE++const char* LLVM_Hs_GetSection(LLVMValueRef globalVal, size_t* strLength) {+ const auto& section = unwrap<GlobalValue>(globalVal)->getSection();+ *strLength = section.size();+ return section.data();+}++unsigned LLVM_Hs_GetCOMDATSelectionKind(const Comdat &comdat) {+ return unsigned(comdat.getSelectionKind());+}++void LLVM_Hs_SetCOMDATSelectionKind(Comdat &comdat, unsigned csk) {+ comdat.setSelectionKind(Comdat::SelectionKind(csk));+}++static LLVMUnnamedAddr unwrap(GlobalValue::UnnamedAddr a) {+ switch (a) {+#define ENUM_CASE(x) case GlobalValue::UnnamedAddr::x: return LLVMUnnamedAddr ## x;+LLVM_HS_FOR_EACH_UNNAMED_ADDR(ENUM_CASE)+#undef ENUM_CASE+ default: return LLVMUnnamedAddrNone;+ }+}++static GlobalValue::UnnamedAddr wrap(LLVMUnnamedAddr a) {+ switch (a) {+#define ENUM_CASE(x) case LLVMUnnamedAddr ## x: return GlobalValue::UnnamedAddr::x;+LLVM_HS_FOR_EACH_UNNAMED_ADDR(ENUM_CASE)+#undef ENUM_CASE+ default: return GlobalValue::UnnamedAddr::None;+ }+}++LLVMUnnamedAddr LLVM_Hs_GetUnnamedAddr(LLVMValueRef globalVal) {+ return unwrap(unwrap<GlobalValue>(globalVal)->getUnnamedAddr());+}++void LLVM_Hs_SetUnnamedAddr(LLVMValueRef globalVal, LLVMUnnamedAddr attr) {+ unwrap<GlobalValue>(globalVal)->setUnnamedAddr(wrap(attr));+}++#define ENUM_CASE(n) \+ static_assert(unsigned(GlobalValue::n) == unsigned(LLVM##n), \+ "TLS Model Enum mismatch");+LLVM_HS_FOR_EACH_THREAD_LOCAL_MODE(ENUM_CASE)+#undef ENUM_CASE++LLVMThreadLocalMode LLVM_Hs_GetThreadLocalMode(LLVMValueRef globalVal) {+ return LLVMThreadLocalMode(unwrap<GlobalValue>(globalVal)->getThreadLocalMode());+}++void LLVM_Hs_SetThreadLocalMode(LLVMValueRef globalVal, LLVMThreadLocalMode mode) {+ unwrap<GlobalValue>(globalVal)->setThreadLocalMode(GlobalValue::ThreadLocalMode(mode));+}++}
+ src/LLVM/Internal/FFI/GlobalVariable.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE+ ForeignFunctionInterface,+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+-- | FFI functions for handling the LLVM GlobalVariable class+module LLVM.Internal.FFI.GlobalVariable where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.PtrHierarchy+import LLVM.Internal.FFI.LLVMCTypes++foreign import ccall unsafe "LLVMIsAGlobalVariable" isAGlobalVariable ::+ Ptr Value -> IO (Ptr GlobalVariable)++foreign import ccall unsafe "LLVMIsGlobalConstant" isGlobalConstant ::+ Ptr GlobalVariable -> IO LLVMBool++foreign import ccall unsafe "LLVMSetGlobalConstant" setGlobalConstant ::+ Ptr GlobalVariable -> LLVMBool -> IO ()++foreign import ccall unsafe "LLVMGetInitializer" getInitializer ::+ Ptr GlobalVariable -> IO (Ptr Constant)++foreign import ccall unsafe "LLVMSetInitializer" setInitializer ::+ Ptr GlobalVariable -> Ptr Constant -> IO ()+
+ src/LLVM/Internal/FFI/InlineAssembly.h view
@@ -0,0 +1,14 @@+#ifndef __LLVM_INTERNAL_FFI__INLINE_ASSEMBLY__H__+#define __LLVM_INTERNAL_FFI__INLINE_ASSEMBLY__H__++#define LLVM_HS_FOR_EACH_ASM_DIALECT(macro) \+ macro(ATT) \+ macro(Intel) \++typedef enum {+#define ENUM_CASE(d) LLVMAsmDialect_ ## d,+ LLVM_HS_FOR_EACH_ASM_DIALECT(ENUM_CASE)+#undef ENUM_CASE+} LLVMAsmDialect;++#endif
+ src/LLVM/Internal/FFI/InlineAssembly.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}++module LLVM.Internal.FFI.InlineAssembly where++import LLVM.Prelude++import Foreign.C+import Foreign.Ptr++import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.PtrHierarchy++foreign import ccall unsafe "LLVMIsAInlineAsm" isAInlineAsm ::+ Ptr Value -> IO (Ptr InlineAsm)++foreign import ccall unsafe "LLVM_Hs_CreateInlineAsm" createInlineAsm ::+ Ptr Type -> CString -> CString -> LLVMBool -> LLVMBool -> AsmDialect -> IO (Ptr InlineAsm)++foreign import ccall unsafe "LLVM_Hs_GetInlineAsmAsmString" getInlineAsmAssemblyString ::+ Ptr InlineAsm -> IO CString++foreign import ccall unsafe "LLVM_Hs_GetInlineAsmConstraintString" getInlineAsmConstraintString ::+ Ptr InlineAsm -> IO CString++foreign import ccall unsafe "LLVM_Hs_InlineAsmHasSideEffects" inlineAsmHasSideEffects ::+ Ptr InlineAsm -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_InlineAsmIsAlignStack" inlineAsmIsAlignStack ::+ Ptr InlineAsm -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_GetInlineAsmDialect" getInlineAsmDialect ::+ Ptr InlineAsm -> IO AsmDialect+
+ src/LLVM/Internal/FFI/InlineAssemblyC.cpp view
@@ -0,0 +1,73 @@+#define __STDC_LIMIT_MACROS+#include "llvm/IR/InlineAsm.h"+#include "llvm/IR/Function.h"+#include "llvm-c/Core.h"++#include "LLVM/Internal/FFI/InlineAssembly.h"++using namespace llvm;++namespace llvm {+static LLVMAsmDialect wrap(InlineAsm::AsmDialect d) {+ switch(d) {+#define ENUM_CASE(x) case InlineAsm::AD_ ## x: return LLVMAsmDialect_ ## x;+LLVM_HS_FOR_EACH_ASM_DIALECT(ENUM_CASE)+#undef ENUM_CASE+ default: return LLVMAsmDialect(0);+ }+}++static InlineAsm::AsmDialect unwrap(LLVMAsmDialect d) {+ switch(d) {+#define ENUM_CASE(x) case LLVMAsmDialect_ ## x: return InlineAsm::AD_ ## x;+LLVM_HS_FOR_EACH_ASM_DIALECT(ENUM_CASE)+#undef ENUM_CASE+ default: return InlineAsm::AsmDialect(0);+ }+}+}++extern "C" {++LLVMValueRef LLVM_Hs_CreateInlineAsm(+ LLVMTypeRef t,+ const char *asmStr,+ const char *constraintsStr,+ LLVMBool hasSideEffects,+ LLVMBool isAlignStack,+ LLVMAsmDialect dialect+) {+ return wrap(+ InlineAsm::get(+ unwrap<FunctionType>(t), + asmStr,+ constraintsStr,+ hasSideEffects,+ isAlignStack,+ unwrap(dialect)+ )+ );+}++const char *LLVM_Hs_GetInlineAsmAsmString(LLVMValueRef v) {+ return unwrap<InlineAsm>(v)->getAsmString().c_str();+}++const char *LLVM_Hs_GetInlineAsmConstraintString(LLVMValueRef v) {+ return unwrap<InlineAsm>(v)->getConstraintString().c_str();+}++LLVMBool LLVM_Hs_InlineAsmHasSideEffects(LLVMValueRef v) {+ return unwrap<InlineAsm>(v)->hasSideEffects();+}++LLVMBool LLVM_Hs_InlineAsmIsAlignStack(LLVMValueRef v) {+ return unwrap<InlineAsm>(v)->isAlignStack();+}++LLVMAsmDialect LLVM_Hs_GetInlineAsmDialect(LLVMValueRef v) {+ return wrap(unwrap<InlineAsm>(v)->getDialect());+}++}+
+ src/LLVM/Internal/FFI/Instruction.h view
@@ -0,0 +1,67 @@+#ifndef __LLVM_INTERNAL_FFI__INSTRUCTION__H__+#define __LLVM_INTERNAL_FFI__INSTRUCTION__H__++#include "llvm/Config/llvm-config.h"++#define LLVM_HS_FOR_EACH_ATOMIC_ORDERING(macro) \+ macro(NotAtomic) \+ macro(Unordered) \+ macro(Monotonic) \+ macro(Acquire) \+ macro(Release) \+ macro(AcquireRelease) \+ macro(SequentiallyConsistent)++#define LLVM_HS_FOR_EACH_RMW_OPERATION(macro) \+ macro(Xchg) \+ macro(Add) \+ macro(Sub) \+ macro(And) \+ macro(Nand) \+ macro(Or) \+ macro(Xor) \+ macro(Max) \+ macro(Min) \+ macro(UMax) \+ macro(UMin)++#define LLVM_HS_FOR_EACH_SYNCRONIZATION_SCOPE(macro) \+ macro(SingleThread) \+ macro(CrossThread)++typedef enum {+#define ENUM_CASE(x) LLVM ## x ## SynchronizationScope,+LLVM_HS_FOR_EACH_SYNCRONIZATION_SCOPE(ENUM_CASE)+#undef ENUM_CASE+} LLVMSynchronizationScope;++#define LLVM_HS_FOR_EACH_FAST_MATH_FLAG(macro) \+ macro(UnsafeAlgebra, unsafeAlgebra) \+ macro(NoNaNs, noNaNs) \+ macro(NoInfs, noInfs) \+ macro(NoSignedZeros, noSignedZeros) \+ macro(AllowReciprocal, allowReciprocal)++typedef enum {+#define ENUM_CASE(x,l) LLVM ## x ## Bit,+LLVM_HS_FOR_EACH_FAST_MATH_FLAG(ENUM_CASE)+#undef ENUM_CASE+} LLVMFastMathFlagBit;++typedef enum {+#define ENUM_CASE(x,l) LLVM ## x = (1 << LLVM ## x ## Bit),+LLVM_HS_FOR_EACH_FAST_MATH_FLAG(ENUM_CASE)+#undef ENUM_CASE+} LLVMFastMathFlags;++#define LLVM_HS_FOR_EACH_TAIL_CALL_KIND(macro) \+ macro(None) \+ macro(Tail) \+ macro(MustTail)++typedef enum {+#define ENUM_CASE(x) LLVM_Hs_TailCallKind_ ## x,+LLVM_HS_FOR_EACH_TAIL_CALL_KIND(ENUM_CASE)+#undef ENUM_CASE+} LLVM_Hs_TailCallKind;+#endif
+ src/LLVM/Internal/FFI/Instruction.hs view
@@ -0,0 +1,181 @@+{-# LANGUAGE+ ForeignFunctionInterface,+ MultiParamTypeClasses,+ UndecidableInstances,+ TemplateHaskell+ #-}+module LLVM.Internal.FFI.Instruction where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.Attribute+import LLVM.Internal.FFI.PtrHierarchy+import LLVM.Internal.FFI.LLVMCTypes++foreign import ccall unsafe "LLVMIsAInstruction" isAInstruction ::+ Ptr Value -> IO (Ptr Instruction)++newtype COpcode = COpcode CUInt++-- get the C API opcode+foreign import ccall unsafe "LLVMGetInstructionOpcode" getInstructionOpcode :: + Ptr Instruction -> IO COpcode++-- get the C++ API opcode (one less level of mapping than for that from the C API)+foreign import ccall unsafe "LLVM_Hs_GetInstructionDefOpcode" getInstructionDefOpcode :: + Ptr Instruction -> IO CPPOpcode++foreign import ccall unsafe "LLVMGetICmpPredicate" getICmpPredicate ::+ Ptr Instruction -> IO ICmpPredicate++foreign import ccall unsafe "LLVM_Hs_GetFCmpPredicate" getFCmpPredicate ::+ Ptr Instruction -> IO FCmpPredicate++foreign import ccall unsafe "LLVM_Hs_GetCallSiteCallingConvention" getCallSiteCallingConvention ::+ Ptr Instruction -> IO CallingConvention++foreign import ccall unsafe "LLVM_Hs_SetCallSiteCallingConvention" setCallSiteCallingConvention ::+ Ptr Instruction -> CallingConvention -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetTailCallKind" getTailCallKind ::+ Ptr Instruction -> IO TailCallKind++foreign import ccall unsafe "LLVM_Hs_SetTailCallKind" setTailCallKind ::+ Ptr Instruction -> TailCallKind -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetCallSiteCalledValue" getCallSiteCalledValue ::+ Ptr Instruction -> IO (Ptr Value)++foreign import ccall unsafe "LLVM_Hs_GetCallSiteAttributeSet" getCallSiteAttributeSet ::+ Ptr Instruction -> IO MixedAttributeSet++foreign import ccall unsafe "LLVM_Hs_SetCallSiteAttributeSet" setCallSiteAttributeSet ::+ Ptr Instruction -> MixedAttributeSet -> IO ()+ +foreign import ccall unsafe "LLVMAddIncoming" addIncoming' ::+ Ptr Instruction -> Ptr (Ptr Value) -> Ptr (Ptr BasicBlock) -> CUInt -> IO ()++addIncoming :: Ptr Instruction -> (CUInt, Ptr (Ptr Value)) -> (CUInt, Ptr (Ptr BasicBlock)) -> IO ()+addIncoming i (nvs, vs) (nbs, bs) | nbs == nvs = addIncoming' i vs bs nbs++foreign import ccall unsafe "LLVMCountIncoming" countIncoming ::+ Ptr Instruction -> IO CUInt++foreign import ccall unsafe "LLVMGetIncomingValue" getIncomingValue ::+ Ptr Instruction -> CUInt -> IO (Ptr Value)++foreign import ccall unsafe "LLVMGetIncomingBlock" getIncomingBlock ::+ Ptr Instruction -> CUInt -> IO (Ptr BasicBlock)+++foreign import ccall unsafe "LLVMAddCase" addCase ::+ Ptr Instruction -> Ptr Constant -> Ptr BasicBlock -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetSwitchCases" getSwitchCases ::+ Ptr Instruction -> Ptr (Ptr Constant) -> Ptr (Ptr BasicBlock) -> IO ()++foreign import ccall unsafe "LLVMAddDestination" addDestination ::+ Ptr Instruction -> Ptr BasicBlock -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetIndirectBrDests" getIndirectBrDests ::+ Ptr Instruction -> Ptr (Ptr BasicBlock) -> IO ()+++foreign import ccall unsafe "LLVM_Hs_GetInstrAlignment" getInstrAlignment ::+ Ptr Instruction -> IO CUInt++foreign import ccall unsafe "LLVM_Hs_SetInstrAlignment" setInstrAlignment ::+ Ptr Instruction -> CUInt -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetAllocaNumElements" getAllocaNumElements ::+ Ptr Instruction -> IO (Ptr Value)++foreign import ccall unsafe "LLVM_Hs_GetAllocatedType" getAllocatedType ::+ Ptr Instruction -> IO (Ptr Type)++foreign import ccall unsafe "LLVM_Hs_GetAtomicOrdering" getAtomicOrdering ::+ Ptr Instruction -> IO MemoryOrdering++foreign import ccall unsafe "LLVM_Hs_GetFailureAtomicOrdering" getFailureAtomicOrdering ::+ Ptr Instruction -> IO MemoryOrdering++foreign import ccall unsafe "LLVM_Hs_GetSynchronizationScope" getSynchronizationScope ::+ Ptr Instruction -> IO SynchronizationScope++getAtomicity :: Ptr Instruction -> IO (SynchronizationScope, MemoryOrdering)+getAtomicity i = return (,) `ap` getSynchronizationScope i `ap` getAtomicOrdering i++foreign import ccall unsafe "LLVM_Hs_GetVolatile" getVolatile ::+ Ptr Instruction -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_GetInBounds" getInBounds ::+ Ptr Value -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_GetAtomicRMWBinOp" getAtomicRMWBinOp ::+ Ptr Instruction -> IO RMWOperation++foreign import ccall unsafe "LLVM_Hs_CountInstStructureIndices" countInstStructureIndices ::+ Ptr Instruction -> IO CUInt++foreign import ccall unsafe "LLVM_Hs_GetInstStructureIndices" getInstStructureIndices ::+ Ptr Instruction -> Ptr CUInt -> IO ()++foreign import ccall unsafe "LLVMAddClause" addClause ::+ Ptr Instruction -> Ptr Constant -> IO ()++foreign import ccall unsafe "LLVMSetCleanup" setCleanup ::+ Ptr Instruction -> LLVMBool -> IO ()++foreign import ccall unsafe "LLVMIsCleanup" isCleanup ::+ Ptr Instruction -> IO LLVMBool++foreign import ccall unsafe "LLVMGetNumClauses" getNumClauses ::+ Ptr Instruction -> IO CUInt++foreign import ccall unsafe "LLVMGetClause" getClause ::+ Ptr Instruction -> CUInt -> IO (Ptr Constant)++foreign import ccall unsafe "LLVM_Hs_SetMetadata" setMetadata ::+ Ptr Instruction -> MDKindID -> Ptr MDNode -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetMetadata" getMetadata ::+ Ptr Instruction -> Ptr MDKindID -> Ptr (Ptr MDNode) -> CUInt -> IO CUInt++foreign import ccall unsafe "LLVM_Hs_GetCleanupPad" getCleanupPad ::+ Ptr Instruction -> IO (Ptr Instruction)++foreign import ccall unsafe "LLVM_Hs_GetUnwindDest" getUnwindDest ::+ Ptr Instruction -> IO (Ptr BasicBlock)++foreign import ccall unsafe "LLVM_Hs_GetParentPad" getParentPad ::+ Ptr Instruction -> IO (Ptr Value)++foreign import ccall unsafe "LLVM_Hs_GetNumArgOperands" getNumArgOperands ::+ Ptr Instruction -> IO CUInt++foreign import ccall unsafe "LLVM_Hs_GetArgOperand" getArgOperand ::+ Ptr Instruction -> CUInt -> IO (Ptr Value)++foreign import ccall unsafe "LLVM_Hs_CatchSwitch_GetParentPad" catchSwitchGetParentPad ::+ Ptr Instruction -> IO (Ptr Value)++foreign import ccall unsafe "LLVM_Hs_CatchSwitch_GetUnwindDest" catchSwitchGetUnwindDest ::+ Ptr Instruction -> IO (Ptr BasicBlock)++foreign import ccall unsafe "LLVM_Hs_CatchSwitch_GetNumHandlers" catchSwitchGetNumHandlers ::+ Ptr Instruction -> IO CUInt++foreign import ccall unsafe "LLVM_Hs_CatchSwitch_GetHandler" catchSwitchGetHandler ::+ Ptr Instruction -> CUInt -> IO (Ptr BasicBlock)++foreign import ccall unsafe "LLVM_Hs_CatchSwitch_AddHandler" catchSwitchAddHandler ::+ Ptr Instruction -> Ptr BasicBlock -> IO ()++foreign import ccall unsafe "LLVM_Hs_CatchRet_GetCatchPad" catchRetGetCatchPad ::+ Ptr Instruction -> IO (Ptr Value)++foreign import ccall unsafe "LLVM_Hs_CatchRet_GetSuccessor" catchRetGetSuccessor ::+ Ptr Instruction -> IO (Ptr BasicBlock)
+ src/LLVM/Internal/FFI/InstructionC.cpp view
@@ -0,0 +1,323 @@+#define __STDC_LIMIT_MACROS+#include "llvm/Config/llvm-config.h"+#include "llvm/IR/LLVMContext.h"+#include "llvm/IR/InstrTypes.h"+#include "llvm/IR/Attributes.h"+#include "llvm/IR/Operator.h"+#include "llvm/IR/BasicBlock.h"+#include "llvm/IR/Metadata.h"+#include "llvm/IR/CallSite.h"++#include "llvm-c/Core.h"++#include "LLVM/Internal/FFI/Metadata.hpp"+#include "LLVM/Internal/FFI/AttributeC.hpp"+#include "LLVM/Internal/FFI/Instruction.h"++using namespace llvm;++namespace llvm {++static LLVMAtomicOrdering wrap(AtomicOrdering l) {+ switch(l) {+#define ENUM_CASE(x) case AtomicOrdering::x: return LLVMAtomicOrdering ## x;+LLVM_HS_FOR_EACH_ATOMIC_ORDERING(ENUM_CASE)+#undef ENUM_CASE+ default: return LLVMAtomicOrdering(0);+ }+}++static LLVMSynchronizationScope wrap(SynchronizationScope l) {+ switch(l) {+#define ENUM_CASE(x) case x: return LLVM ## x ## SynchronizationScope;+LLVM_HS_FOR_EACH_SYNCRONIZATION_SCOPE(ENUM_CASE)+#undef ENUM_CASE+ default: return LLVMSynchronizationScope(0);+ }+}++static LLVMAtomicRMWBinOp wrap(AtomicRMWInst::BinOp l) {+ switch(l) {+#define ENUM_CASE(x) case AtomicRMWInst::x: return LLVMAtomicRMWBinOp ## x;+LLVM_HS_FOR_EACH_RMW_OPERATION(ENUM_CASE)+#undef ENUM_CASE+ default: return LLVMAtomicRMWBinOp(0);+ }+}++LLVMFastMathFlags wrap(FastMathFlags f) {+ unsigned r = 0;+#define ENUM_CASE(u,l) if (f.l()) r |= unsigned(LLVM ## u);+LLVM_HS_FOR_EACH_FAST_MATH_FLAG(ENUM_CASE)+#undef ENUM_CASE+ return LLVMFastMathFlags(r);+}++}++extern "C" {++unsigned LLVM_Hs_GetInstructionDefOpcode(LLVMValueRef val) {+ return unwrap<Instruction>(val)->getOpcode();+}++unsigned LLVM_Hs_HasNoSignedWrap(LLVMValueRef val) {+ return unwrap<OverflowingBinaryOperator>(val)->hasNoSignedWrap();+}++unsigned LLVM_Hs_HasNoUnsignedWrap(LLVMValueRef val) {+ return unwrap<OverflowingBinaryOperator>(val)->hasNoUnsignedWrap();+}++int LLVM_Hs_IsExact(LLVMValueRef val) {+ return unwrap<PossiblyExactOperator>(val)->isExact();+}++LLVMFastMathFlags LLVM_Hs_GetFastMathFlags(LLVMValueRef val) {+ return wrap(unwrap<Instruction>(val)->getFastMathFlags());+}++LLVMValueRef LLVM_Hs_GetCallSiteCalledValue(LLVMValueRef i) {+ return wrap(CallSite(unwrap<Instruction>(i)).getCalledValue());+}++const AttributeSetImpl *LLVM_Hs_GetCallSiteAttributeSet(LLVMValueRef i) {+ return wrap(CallSite(unwrap<Instruction>(i)).getAttributes());+}++void LLVM_Hs_SetCallSiteAttributeSet(LLVMValueRef i, const AttributeSetImpl *asi) {+ CallSite(unwrap<Instruction>(i)).setAttributes(unwrap(asi));+}++unsigned LLVM_Hs_GetCallSiteCallingConvention(LLVMValueRef i) {+ return unsigned(CallSite(unwrap<Instruction>(i)).getCallingConv());+}++void LLVM_Hs_SetCallSiteCallingConvention(LLVMValueRef i, unsigned cc) {+ CallSite(unwrap<Instruction>(i)).setCallingConv(llvm::CallingConv::ID(cc));+}++#define CHECK(name) \+ static_assert(unsigned(llvm::CallInst::TCK_##name) == \+ unsigned(LLVM_Hs_TailCallKind_##name), \+ "LLVM_Hs_TailCallKind enum out of sync w/ " \+ "llvm::CallInst::TailCallKind for " #name);+LLVM_HS_FOR_EACH_TAIL_CALL_KIND(CHECK)+#undef CHECK++unsigned LLVM_Hs_GetTailCallKind(LLVMValueRef i) {+ return unwrap<CallInst>(i)->getTailCallKind();+}++void LLVM_Hs_SetTailCallKind(LLVMValueRef i, unsigned kind) {+ return unwrap<CallInst>(i)->setTailCallKind(llvm::CallInst::TailCallKind(kind));+}++LLVMValueRef LLVM_Hs_GetAllocaNumElements(LLVMValueRef a) {+ return wrap(unwrap<AllocaInst>(a)->getArraySize());+}++LLVMTypeRef LLVM_Hs_GetAllocatedType(LLVMValueRef a) {+ return wrap(unwrap<AllocaInst>(a)->getAllocatedType());+}++// ------------------------------------------------------------++#define LLVM_HS_FOR_EACH_ALIGNMENT_INST(macro) \+ macro(Alloca) \+ macro(Load) \+ macro(Store)++unsigned LLVM_Hs_GetInstrAlignment(LLVMValueRef l) {+ switch(unwrap<Instruction>(l)->getOpcode()) {+#define ENUM_CASE(n) case Instruction::n: return unwrap<n ## Inst>(l)->getAlignment();+ LLVM_HS_FOR_EACH_ALIGNMENT_INST(ENUM_CASE)+#undef ENUM_CASE+ default: return 0;+ }+}++void LLVM_Hs_SetInstrAlignment(LLVMValueRef l, unsigned a) {+ switch(unwrap<Instruction>(l)->getOpcode()) {+#define ENUM_CASE(n) case Instruction::n: unwrap<n ## Inst>(l)->setAlignment(a); break;+ LLVM_HS_FOR_EACH_ALIGNMENT_INST(ENUM_CASE)+#undef ENUM_CASE+ }+}++// ------------------------------------------------------------++#define LLVM_HS_FOR_EACH_ATOMIC_INST(macro) \+ macro(Load,) \+ macro(Store,) \+ macro(Fence,) \+ macro(AtomicCmpXchg,Success) \+ macro(AtomicRMW,)++LLVMAtomicOrdering LLVM_Hs_GetAtomicOrdering(LLVMValueRef i) {+ switch(unwrap<Instruction>(i)->getOpcode()) {+#define ENUM_CASE(n,s) case Instruction::n: return wrap(unwrap<n ## Inst>(i)->get ## s ## Ordering());+ LLVM_HS_FOR_EACH_ATOMIC_INST(ENUM_CASE)+#undef ENUM_CASE+ default: return LLVMAtomicOrdering(0);+ }+}++LLVMAtomicOrdering LLVM_Hs_GetFailureAtomicOrdering(LLVMValueRef i) {+ switch(unwrap<Instruction>(i)->getOpcode()) {+ case Instruction::AtomicCmpXchg: return wrap(unwrap<AtomicCmpXchgInst>(i)->getFailureOrdering());+ default: return LLVMAtomicOrdering(0);+ }+}++LLVMSynchronizationScope LLVM_Hs_GetSynchronizationScope(LLVMValueRef i) {+ switch(unwrap<Instruction>(i)->getOpcode()) {+#define ENUM_CASE(n,s) case Instruction::n: return wrap(unwrap<n ## Inst>(i)->getSynchScope());+ LLVM_HS_FOR_EACH_ATOMIC_INST(ENUM_CASE)+#undef ENUM_CASE+ default: return LLVMSynchronizationScope(0);+ }+}++#define LLVM_HS_FOR_EACH_VOLATILITY_INST(macro) \+ macro(Load) \+ macro(Store) \+ macro(AtomicCmpXchg) \+ macro(AtomicRMW)++LLVMBool LLVM_Hs_GetVolatile(LLVMValueRef i) {+ switch(unwrap<Instruction>(i)->getOpcode()) {+#define ENUM_CASE(n) case Instruction::n: return unwrap<n ## Inst>(i)->isVolatile();+ LLVM_HS_FOR_EACH_VOLATILITY_INST(ENUM_CASE)+#undef ENUM_CASE+ default: return LLVMBool(0);+ }+}++// ------------------------------------------------------------++LLVMBool LLVM_Hs_GetInBounds(LLVMValueRef i) {+ return unwrap<GEPOperator>(i)->isInBounds();+}++LLVMAtomicRMWBinOp LLVM_Hs_GetAtomicRMWBinOp(LLVMValueRef i) {+ return wrap(unwrap<AtomicRMWInst>(i)->getOperation());+}++LLVMRealPredicate LLVM_Hs_GetFCmpPredicate(LLVMValueRef Inst) {+ if (FCmpInst *I = dyn_cast<FCmpInst>(unwrap(Inst)))+ return (LLVMRealPredicate)I->getPredicate();+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(unwrap(Inst)))+ if (CE->getOpcode() == Instruction::FCmp)+ return (LLVMRealPredicate)CE->getPredicate();+ return (LLVMRealPredicate)0;+}++unsigned LLVM_Hs_CountInstStructureIndices(LLVMValueRef v) {+ if (ExtractValueInst *i = dyn_cast<ExtractValueInst>(unwrap(v))) return i->getNumIndices();+ if (InsertValueInst *i = dyn_cast<InsertValueInst>(unwrap(v))) return i->getNumIndices();+ return 0;+}++void LLVM_Hs_GetInstStructureIndices(LLVMValueRef v, unsigned *is) {+ ArrayRef<unsigned> a;+ if (ExtractValueInst *i = dyn_cast<ExtractValueInst>(unwrap(v))) a = i->getIndices();+ if (InsertValueInst *i = dyn_cast<InsertValueInst>(unwrap(v))) a = i->getIndices();+ std::copy(a.begin(), a.end(), is);+}++void LLVM_Hs_GetSwitchCases(+ LLVMValueRef v,+ LLVMValueRef *values,+ LLVMBasicBlockRef *dests+) {+ SwitchInst *s = unwrap<SwitchInst>(v);+ for(SwitchInst::CaseIt i = s->case_begin(); i != s->case_end(); ++i, ++values, ++dests) {+ *values = wrap(i.getCaseValue());+ *dests = wrap(i.getCaseSuccessor());+ }+}++void LLVM_Hs_GetIndirectBrDests(+ LLVMValueRef v,+ LLVMBasicBlockRef *dests+) {+ IndirectBrInst *ib = unwrap<IndirectBrInst>(v);+ for(unsigned i=0; i != ib->getNumDestinations(); ++i, ++dests)+ *dests = wrap(ib->getDestination(i));+}++inline Metadata **unwrap(LLVMMetadataRef *vals) {+ return reinterpret_cast<Metadata**>(vals);+}++void LLVM_Hs_SetMetadata(LLVMValueRef inst, unsigned kindID, LLVMMetadataRef md) {+ MDNode *N = md ? unwrap<MDNode>(md) : nullptr;+ unwrap<Instruction>(inst)->setMetadata(kindID, N);+}++unsigned LLVM_Hs_GetMetadata(+ LLVMValueRef i,+ unsigned *kinds,+ LLVMMetadataRef *nodes,+ unsigned nKinds+) {+ SmallVector<std::pair<unsigned, MDNode *>, 4> mds;+ unwrap<Instruction>(i)->getAllMetadata(mds);+ if (mds.size() <= nKinds) {+ for(unsigned i=0; i<mds.size(); ++i) {+ kinds[i] = mds[i].first;+ nodes[i] = wrap(mds[i].second);+ }+ }+ return mds.size();+}++LLVMValueRef LLVM_Hs_GetCleanupPad(LLVMValueRef i) {+ return wrap(unwrap<CleanupReturnInst>(i)->getCleanupPad());+}++LLVMBasicBlockRef LLVM_Hs_GetUnwindDest(LLVMValueRef i) {+ return wrap(unwrap<CleanupReturnInst>(i)->getUnwindDest());+}++LLVMValueRef LLVM_Hs_GetParentPad(LLVMValueRef i) {+ return wrap(unwrap<FuncletPadInst>(i)->getParentPad());+}++unsigned LLVM_Hs_GetNumArgOperands(LLVMValueRef i) {+ return unwrap<FuncletPadInst>(i)->getNumArgOperands();+}++LLVMValueRef LLVM_Hs_GetArgOperand(LLVMValueRef i, unsigned op) {+ return wrap(unwrap<FuncletPadInst>(i)->getArgOperand(op));+}++LLVMValueRef LLVM_Hs_CatchSwitch_GetParentPad(LLVMValueRef i) {+ return wrap(unwrap<CatchSwitchInst>(i)->getParentPad());+}++LLVMBasicBlockRef LLVM_Hs_CatchSwitch_GetUnwindDest(LLVMValueRef i) {+ return wrap(unwrap<CatchSwitchInst>(i)->getUnwindDest());+}++unsigned LLVM_Hs_CatchSwitch_GetNumHandlers(LLVMValueRef i) {+ return unwrap<CatchSwitchInst>(i)->getNumHandlers();+}++LLVMBasicBlockRef LLVM_Hs_CatchSwitch_GetHandler(LLVMValueRef instr, unsigned i) {+ return wrap(*(unwrap<CatchSwitchInst>(instr)->handler_begin() + i));+}++void LLVM_Hs_CatchSwitch_AddHandler(LLVMValueRef instr, LLVMBasicBlockRef bb) {+ unwrap<CatchSwitchInst>(instr)->addHandler(unwrap(bb));+}++LLVMValueRef LLVM_Hs_CatchRet_GetCatchPad(LLVMValueRef i) {+ return wrap(unwrap<CatchReturnInst>(i)->getCatchPad());+}++LLVMBasicBlockRef LLVM_Hs_CatchRet_GetSuccessor(LLVMValueRef i) {+ return wrap(unwrap<CatchReturnInst>(i)->getSuccessor());+}+}
+ src/LLVM/Internal/FFI/InstructionDefs.hsc view
@@ -0,0 +1,61 @@+-- This module translates the instruction data in "llvm/Instruction.def" into a Haskell data structure,+-- so it may be accessed conveniently with Template Haskell code+module LLVM.Internal.FFI.InstructionDefs where++import LLVM.Prelude++import LLVM.Internal.FFI.LLVMCTypes++#define FIRST_TERM_INST(num) struct inst { const char *kind; int opcode; const char *name; const char *clas; } insts[] = { { "Terminator", },++#define FIRST_BINARY_INST(num) { "Binary" },+#define FIRST_MEMORY_INST(num) { "Memory" },+#define FIRST_CAST_INST(num) { "Cast" },+#define FIRST_OTHER_INST(num) { "Other" },+#define FIRST_FUNCLETPAD_INST(num) { "FuncletPad" },++#define HANDLE_INST(num,opcode,class) { 0, num, #opcode, #class, },++#define LAST_OTHER_INST(num) { 0, 0, 0, 0, } };++#include "llvm/Config/llvm-config.h"++#include "llvm/IR/Instruction.def"++#{+define hsc_inject() { \+ hsc_printf("["); \+ struct inst *i; \+ const char *kind; \+ int first = 1; \+ for(i = insts; i->kind || i->opcode; ++i) { \+ if (i->kind) { kind = i->kind; continue; } \+ if (!first) { hsc_printf("\n ,"); } else { first = 0; } \+ hsc_printf( \+ " (CPPOpcode %d,\"%s\",\"%s\", %s)", \+ i->opcode, i->name, i->clas, kind \+ ); \+ } \+ hsc_printf(" ] "); \+}+}++data InstructionKind = Terminator | Binary | Memory | Cast | FuncletPad | Other+ deriving (Eq, Ord, Show)++data InstructionDef = InstructionDef {+ cppOpcode :: CPPOpcode,+ cAPIName :: String,+ cAPIClassName :: String,+ instructionKind :: InstructionKind+ }+ deriving (Eq, Ord, Show)++instructionDefs :: [InstructionDef]+instructionDefs = [ + InstructionDef o an acn k+ | (o, an, acn, k) <-+ #{inject},+ an /= "UserOp1" && an /= "UserOp2"+ ]+
+ src/LLVM/Internal/FFI/Iterate.hs view
@@ -0,0 +1,13 @@+-- | Functions to help handle LLVM iteration patterns+module LLVM.Internal.FFI.Iterate where++import LLVM.Prelude++import Foreign.Ptr++-- | retrieve a sequence of objects which form a linked list, given an action to+-- | retrieve the first member and an action to proceed through the list+getXs :: IO (Ptr a) -> (Ptr a -> IO (Ptr a)) -> IO [Ptr a]+getXs firstX nextX = walk =<< firstX+ where walk x | x == nullPtr = return []+ walk x = (x:) <$> (walk <=< nextX) x
+ src/LLVM/Internal/FFI/LLVMCTypes.hsc view
@@ -0,0 +1,266 @@+{-# LANGUAGE+ GeneralizedNewtypeDeriving+ #-}+-- | Define types which correspond cleanly with some simple types on the C/C++ side.+-- Encapsulate hsc macro weirdness here, supporting higher-level tricks elsewhere.+module LLVM.Internal.FFI.LLVMCTypes where++import LLVM.Prelude++#define __STDC_LIMIT_MACROS+#include "llvm-c/Core.h"+#include "llvm-c/Linker.h"+#include "llvm-c/OrcBindings.h"+#include "llvm-c/Target.h"+#include "llvm-c/TargetMachine.h"+#include "LLVM/Internal/FFI/Attribute.h"+#include "LLVM/Internal/FFI/Instruction.h"+#include "LLVM/Internal/FFI/Value.h"+#include "LLVM/Internal/FFI/SMDiagnostic.h"+#include "LLVM/Internal/FFI/InlineAssembly.h"+#include "LLVM/Internal/FFI/Target.h"+#include "LLVM/Internal/FFI/CallingConvention.h"+#include "LLVM/Internal/FFI/GlobalValue.h"+#include "LLVM/Internal/FFI/Type.h"+#include "LLVM/Internal/FFI/Constant.h"+#include "LLVM/Internal/FFI/Analysis.h"+#include "LLVM/Internal/FFI/LibFunc.h"+#include "LLVM/Internal/FFI/OrcJIT.h"++import Language.Haskell.TH.Quote++import Data.Bits+import Foreign.C+import Foreign.Storable++#{+define hsc_inject(l, typ, cons, hprefix, recmac) { \+ struct { const char *s; unsigned n; } *p, list[] = { LLVM_HS_FOR_EACH_ ## l(recmac) }; \+ for(p = list; p < list + sizeof(list)/sizeof(list[0]); ++p) { \+ hsc_printf(#hprefix "%s :: " #typ "\n", p->s); \+ hsc_printf(#hprefix "%s = " #cons " %u\n", p->s, p->n); \+ } \+ hsc_printf(#hprefix "P :: QuasiQuoter\n" \+ #hprefix "P = QuasiQuoter {\n" \+ " quoteExp = undefined,\n" \+ " quotePat = \\s -> dataToPatQ (const Nothing) $ case s of"); \+ for(p = list; p < list + sizeof(list)/sizeof(list[0]); ++p) { \+ hsc_printf("\n \"%s\" -> " #hprefix "%s", p->s, p->s); \+ } \+ hsc_printf("\n x -> error $ \"bad quasiquoted FFI constant for " #hprefix ": \" ++ x"); \+ hsc_printf(",\n" \+ " quoteType = undefined,\n" \+ " quoteDec = undefined\n" \+ " }\n"); \+}+}++deriving instance Data CUInt++newtype LLVMBool = LLVMBool CUInt++newtype OwnerTransfered a = OwnerTransfered a+ deriving (Storable)++newtype NothingAsMinusOne h = NothingAsMinusOne CInt+ deriving (Storable)++newtype NothingAsEmptyString c = NothingAsEmptyString c+ deriving (Storable)++newtype CPPOpcode = CPPOpcode CUInt+ deriving (Eq, Ord, Show, Typeable, Data)++newtype ICmpPredicate = ICmpPredicate CUInt+ deriving (Eq, Ord, Show, Typeable, Data)+#{enum ICmpPredicate, ICmpPredicate,+ iCmpPredEQ = LLVMIntEQ,+ iCmpPredNE = LLVMIntNE,+ iCmpPredUGT = LLVMIntUGT,+ iCmpPredUGE = LLVMIntUGE,+ iCmpPredULT = LLVMIntULT,+ iCmpPredULE = LLVMIntULE,+ iCmpPredSGT = LLVMIntSGT,+ iCmpPredSGE = LLVMIntSGE,+ iCmpPredSLT = LLVMIntSLT,+ iCmpPredSLE = LLVMIntSLE+}++newtype FCmpPredicate = FCmpPredicate CUInt+ deriving (Eq, Ord, Show, Typeable, Data)+#{enum FCmpPredicate, FCmpPredicate,+ fCmpPredFalse = LLVMRealPredicateFalse,+ fCmpPredOEQ = LLVMRealOEQ,+ fCmpPredOGT = LLVMRealOGT,+ fCmpPredOGE = LLVMRealOGE,+ fCmpPredOLT = LLVMRealOLT,+ fCmpPredOLE = LLVMRealOLE,+ fCmpPredONE = LLVMRealONE,+ fCmpPredORD = LLVMRealORD,+ fCmpPredUNO = LLVMRealUNO,+ fCmpPredUEQ = LLVMRealUEQ,+ fCmpPredUGT = LLVMRealUGT,+ fCmpPredUGE = LLVMRealUGE,+ fCmpPredULT = LLVMRealULT,+ fCmpPredULE = LLVMRealULE,+ fCmpPredUNE = LLVMRealUNE,+ fcmpPredTrue = LLVMRealPredicateTrue+}++newtype MDKindID = MDKindID CUInt+ deriving (Storable)++newtype FastMathFlags = FastMathFlags CUInt+ deriving (Eq, Ord, Show, Typeable, Data, Num, Bits)+#define FMF_Rec(n,l) { #n, LLVM ## n, },+#{inject FAST_MATH_FLAG, FastMathFlags, FastMathFlags, fastMathFlags, FMF_Rec}++newtype MemoryOrdering = MemoryOrdering CUInt+ deriving (Eq, Typeable, Data)+#define MO_Rec(n) { #n, LLVMAtomicOrdering ## n },+#{inject ATOMIC_ORDERING, MemoryOrdering, MemoryOrdering, memoryOrdering, MO_Rec}++newtype UnnamedAddr = UnnamedAddr CUInt+ deriving (Eq, Typeable, Data)+#define UA_Rec(n) { #n, LLVMUnnamedAddr ## n },+#{inject UNNAMED_ADDR, UnnamedAddr, UnnamedAddr, unnamedAddr, UA_Rec}++newtype SynchronizationScope = SynchronizationScope CUInt+ deriving (Eq, Typeable, Data)+#define SS_Rec(n) { #n, LLVM ## n ## SynchronizationScope },+#{inject SYNCRONIZATION_SCOPE, SynchronizationScope, SynchronizationScope, synchronizationScope, SS_Rec}++newtype TailCallKind = TailCallKind CUInt+ deriving (Eq, Typeable, Data)+#define TCK_Rec(n) { #n, LLVM_Hs_TailCallKind_ ## n },+#{inject TAIL_CALL_KIND, TailCallKind, TailCallKind, tailCallKind, TCK_Rec}++newtype Linkage = Linkage CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define LK_Rec(n) { #n, LLVM ## n ## Linkage },+#{inject LINKAGE, Linkage, Linkage, linkage, LK_Rec}++newtype Visibility = Visibility CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define VIS_Rec(n) { #n, LLVM ## n ## Visibility },+#{inject VISIBILITY, Visibility, Visibility, visibility, VIS_Rec}++newtype COMDATSelectionKind = COMDATSelectionKind CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define CSK(n) { #n, LLVM_Hs_COMDAT_Selection_Kind_ ## n },+#{inject COMDAT_SELECTION_KIND, COMDATSelectionKind, COMDATSelectionKind, comdatSelectionKind, CSK}++newtype DLLStorageClass = DLLStorageClass CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define DLLSC_Rec(n) { #n, LLVM ## n ## StorageClass },+#{inject DLL_STORAGE_CLASS, DLLStorageClass, DLLStorageClass, dllStorageClass, DLLSC_Rec}++newtype CallingConvention = CallingConvention CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define CC_Rec(l, n) { #l, LLVM_Hs_CallingConvention_ ## l },+#{inject CALLING_CONVENTION, CallingConvention, CallingConvention, callingConvention, CC_Rec}++newtype ThreadLocalMode = ThreadLocalMode CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define TLS_Rec(n) { #n, LLVM ## n },+#{inject THREAD_LOCAL_MODE, ThreadLocalMode, ThreadLocalMode, threadLocalMode, TLS_Rec}++newtype ValueSubclassId = ValueSubclassId CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define VSID_Rec(n) { #n, LLVM ## n ## SubclassId },+#{inject VALUE_SUBCLASS, ValueSubclassId, ValueSubclassId, valueSubclassId, VSID_Rec}++newtype DiagnosticKind = DiagnosticKind CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define DK_Rec(n) { #n, LLVMDiagnosticKind ## n },+#{inject DIAGNOSTIC_KIND, DiagnosticKind, DiagnosticKind, diagnosticKind, DK_Rec}++newtype AsmDialect = AsmDialect CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define ASM_Rec(n) { #n, LLVMAsmDialect_ ## n },+#{inject ASM_DIALECT, AsmDialect, AsmDialect, asmDialect, ASM_Rec}++newtype RMWOperation = RMWOperation CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define RMWOp_Rec(n) { #n, LLVMAtomicRMWBinOp ## n },+#{inject RMW_OPERATION, RMWOperation, RMWOperation, rmwOperation, RMWOp_Rec}++newtype RelocModel = RelocModel CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define RM_Rec(n,m) { #n, LLVMReloc ## n },+#{inject RELOC_MODEL, RelocModel, RelocModel, relocModel, RM_Rec}++newtype CodeModel = CodeModel CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define CM_Rec(n) { #n, LLVMCodeModel ## n },+#{inject CODE_MODEL, CodeModel, CodeModel, codeModel, CM_Rec}++newtype CodeGenOptLevel = CodeGenOptLevel CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define CGOL_Rec(n) { #n, LLVMCodeGenLevel ## n },+#{inject CODE_GEN_OPT_LEVEL, CodeGenOptLevel, CodeGenOptLevel, codeGenOptLevel, CGOL_Rec}++newtype CodeGenFileType = CodeGenFileType CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define CGFT_Rec(n) { #n, LLVM ## n ## File },+#{inject CODE_GEN_FILE_TYPE, CodeGenFileType, CodeGenFileType, codeGenFileType, CGFT_Rec}++newtype FloatABIType = FloatABIType CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define FAT_Rec(n) { #n, LLVM_Hs_FloatABI_ ## n },+#{inject FLOAT_ABI, FloatABIType, FloatABIType, floatABI, FAT_Rec}++newtype FPOpFusionMode = FPOpFusionMode CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define FPOFM_Rec(n) { #n, LLVM_Hs_FPOpFusionMode_ ## n },+#{inject FP_OP_FUSION_MODE, FPOpFusionMode, FPOpFusionMode, fpOpFusionMode, FPOFM_Rec}++newtype TargetOptionFlag = TargetOptionFlag CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define TOF_Rec(n) { #n, LLVM_Hs_TargetOptionFlag_ ## n },+#{inject TARGET_OPTION_FLAG, TargetOptionFlag, TargetOptionFlag, targetOptionFlag, TOF_Rec}++newtype TypeKind = TypeKind CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define TK_Rec(n) { #n, LLVM ## n ## TypeKind },+#{inject TYPE_KIND, TypeKind, TypeKind, typeKind, TK_Rec}++#define COMMA ,+#define IF_T(z) z+#define IF_F(z)+#define IF2(x) IF_ ## x+#define IF(x) IF2(x)+#define OR_TT T+#define OR_TF T+#define OR_FT T+#define OR_FF F+#define OR(x,y) OR_ ## x ## y+newtype ParameterAttributeKind = ParameterAttributeKind CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define PAK_Rec(n,p,r,f) IF(OR(p,r))({ #n COMMA LLVM_Hs_AttributeKind_ ## n} COMMA)+#{inject ATTRIBUTE_KIND, ParameterAttributeKind, ParameterAttributeKind, parameterAttributeKind, PAK_Rec}++newtype FunctionAttributeKind = FunctionAttributeKind CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define FAK_Rec(n,p,r,f) IF(f)({ #n COMMA LLVM_Hs_AttributeKind_ ## n} COMMA)+#{inject ATTRIBUTE_KIND, FunctionAttributeKind, FunctionAttributeKind, functionAttributeKind, FAK_Rec}++newtype FloatSemantics = FloatSemantics CUInt+ deriving (Eq, Read, Show, Typeable, Data)+#define FS_Rec(n) { #n, LLVMFloatSemantics ## n },+#{inject FLOAT_SEMANTICS, FloatSemantics, FloatSemantics, floatSemantics, FS_Rec}++newtype VerifierFailureAction = VerifierFailureAction CUInt+ deriving (Eq, Read, Show, Bits, Typeable, Data, Num)+#define VFA_Rec(n) { #n, LLVM ## n ## Action },+#{inject VERIFIER_FAILURE_ACTION, VerifierFailureAction, VerifierFailureAction, verifierFailureAction, VFA_Rec}++newtype LibFunc = LibFunc CUInt+ deriving (Eq, Read, Show, Bits, Typeable, Data, Num, Storable)+#define LF_Rec(n) { #n, LLVMLibFunc__ ## n },+#{inject LIB_FUNC, LibFunc, LibFunc, libFunc__, LF_Rec}++newtype JITSymbolFlags = JITSymbolFlags CUInt+ deriving (Eq, Read, Show, Bits, Typeable, Data, Num, Storable)+#define SF_Rec(n) { #n, LLVMJITSymbolFlag ## n },+#{inject JIT_SYMBOL_FLAG, JITSymbolFlags, JITSymbolFlags, jitSymbolFlags, SF_Rec}
+ src/LLVM/Internal/FFI/LibFunc.h view
@@ -0,0 +1,332 @@+#ifndef __LLVM_INTERNAL_FFI__LIB_FUNC__H__+#define __LLVM_INTERNAL_FFI__LIB_FUNC__H__++#define LLVM_HS_FOR_EACH_LIB_FUNC(macro) \+ macro(under_IO_getc) \+ macro(under_IO_putc) \+ macro(ZdaPv) \+ macro(ZdaPvRKSt9nothrow_t) \+ macro(ZdlPv) \+ macro(ZdlPvRKSt9nothrow_t) \+ macro(Znaj) \+ macro(ZnajRKSt9nothrow_t) \+ macro(Znam) \+ macro(ZnamRKSt9nothrow_t) \+ macro(Znwj) \+ macro(ZnwjRKSt9nothrow_t) \+ macro(Znwm) \+ macro(ZnwmRKSt9nothrow_t) \+ macro(cospi) \+ macro(cospif) \+ macro(cxa_atexit) \+ macro(cxa_guard_abort) \+ macro(cxa_guard_acquire) \+ macro(cxa_guard_release) \+ macro(dunder_isoc99_scanf) \+ macro(dunder_isoc99_sscanf) \+ macro(memcpy_chk) \+ macro(sincospi_stret) \+ macro(sincospif_stret) \+ macro(sinpi) \+ macro(sinpif) \+ macro(sqrt_finite) \+ macro(sqrtf_finite) \+ macro(sqrtl_finite) \+ macro(dunder_strdup) \+ macro(dunder_strndup) \+ macro(dunder_strtok_r) \+ macro(abs) \+ macro(access) \+ macro(acos) \+ macro(acosf) \+ macro(acosh) \+ macro(acoshf) \+ macro(acoshl) \+ macro(acosl) \+ macro(asin) \+ macro(asinf) \+ macro(asinh) \+ macro(asinhf) \+ macro(asinhl) \+ macro(asinl) \+ macro(atan) \+ macro(atan2) \+ macro(atan2f) \+ macro(atan2l) \+ macro(atanf) \+ macro(atanh) \+ macro(atanhf) \+ macro(atanhl) \+ macro(atanl) \+ macro(atof) \+ macro(atoi) \+ macro(atol) \+ macro(atoll) \+ macro(bcmp) \+ macro(bcopy) \+ macro(bzero) \+ macro(calloc) \+ macro(cbrt) \+ macro(cbrtf) \+ macro(cbrtl) \+ macro(ceil) \+ macro(ceilf) \+ macro(ceill) \+ macro(chmod) \+ macro(chown) \+ macro(clearerr) \+ macro(closedir) \+ macro(copysign) \+ macro(copysignf) \+ macro(copysignl) \+ macro(cos) \+ macro(cosf) \+ macro(cosh) \+ macro(coshf) \+ macro(coshl) \+ macro(cosl) \+ macro(ctermid) \+ macro(exp) \+ macro(exp10) \+ macro(exp10f) \+ macro(exp10l) \+ macro(exp2) \+ macro(exp2f) \+ macro(exp2l) \+ macro(expf) \+ macro(expl) \+ macro(expm1) \+ macro(expm1f) \+ macro(expm1l) \+ macro(fabs) \+ macro(fabsf) \+ macro(fabsl) \+ macro(fclose) \+ macro(fdopen) \+ macro(feof) \+ macro(ferror) \+ macro(fflush) \+ macro(ffs) \+ macro(ffsl) \+ macro(ffsll) \+ macro(fgetc) \+ macro(fgetpos) \+ macro(fgets) \+ macro(fileno) \+ macro(fiprintf) \+ macro(flockfile) \+ macro(floor) \+ macro(floorf) \+ macro(floorl) \+ macro(fmax) \+ macro(fmaxf) \+ macro(fmaxl) \+ macro(fmin) \+ macro(fminf) \+ macro(fminl) \+ macro(fmod) \+ macro(fmodf) \+ macro(fmodl) \+ macro(fopen) \+ macro(fopen64) \+ macro(fprintf) \+ macro(fputc) \+ macro(fputs) \+ macro(fread) \+ macro(free) \+ macro(frexp) \+ macro(frexpf) \+ macro(frexpl) \+ macro(fscanf) \+ macro(fseek) \+ macro(fseeko) \+ macro(fseeko64) \+ macro(fsetpos) \+ macro(fstat) \+ macro(fstat64) \+ macro(fstatvfs) \+ macro(fstatvfs64) \+ macro(ftell) \+ macro(ftello) \+ macro(ftello64) \+ macro(ftrylockfile) \+ macro(funlockfile) \+ macro(fwrite) \+ macro(getc) \+ macro(getc_unlocked) \+ macro(getchar) \+ macro(getenv) \+ macro(getitimer) \+ macro(getlogin_r) \+ macro(getpwnam) \+ macro(gets) \+ macro(gettimeofday) \+ macro(htonl) \+ macro(htons) \+ macro(iprintf) \+ macro(isascii) \+ macro(isdigit) \+ macro(labs) \+ macro(lchown) \+ macro(ldexp) \+ macro(ldexpf) \+ macro(ldexpl) \+ macro(llabs) \+ macro(log) \+ macro(log10) \+ macro(log10f) \+ macro(log10l) \+ macro(log1p) \+ macro(log1pf) \+ macro(log1pl) \+ macro(log2) \+ macro(log2f) \+ macro(log2l) \+ macro(logb) \+ macro(logbf) \+ macro(logbl) \+ macro(logf) \+ macro(logl) \+ macro(lstat) \+ macro(lstat64) \+ macro(malloc) \+ macro(memalign) \+ macro(memccpy) \+ macro(memchr) \+ macro(memcmp) \+ macro(memcpy) \+ macro(memmove) \+ macro(memrchr) \+ macro(memset) \+ macro(memset_pattern16) \+ macro(mkdir) \+ macro(mktime) \+ macro(modf) \+ macro(modff) \+ macro(modfl) \+ macro(nearbyint) \+ macro(nearbyintf) \+ macro(nearbyintl) \+ macro(ntohl) \+ macro(ntohs) \+ macro(open) \+ macro(open64) \+ macro(opendir) \+ macro(pclose) \+ macro(perror) \+ macro(popen) \+ macro(posix_memalign) \+ macro(pow) \+ macro(powf) \+ macro(powl) \+ macro(pread) \+ macro(printf) \+ macro(putc) \+ macro(putchar) \+ macro(puts) \+ macro(pwrite) \+ macro(qsort) \+ macro(read) \+ macro(readlink) \+ macro(realloc) \+ macro(reallocf) \+ macro(realpath) \+ macro(remove) \+ macro(rename) \+ macro(rewind) \+ macro(rint) \+ macro(rintf) \+ macro(rintl) \+ macro(rmdir) \+ macro(round) \+ macro(roundf) \+ macro(roundl) \+ macro(scanf) \+ macro(setbuf) \+ macro(setitimer) \+ macro(setvbuf) \+ macro(sin) \+ macro(sinf) \+ macro(sinh) \+ macro(sinhf) \+ macro(sinhl) \+ macro(sinl) \+ macro(siprintf) \+ macro(snprintf) \+ macro(sprintf) \+ macro(sqrt) \+ macro(sqrtf) \+ macro(sqrtl) \+ macro(sscanf) \+ macro(stat) \+ macro(stat64) \+ macro(statvfs) \+ macro(statvfs64) \+ macro(stpcpy) \+ macro(stpncpy) \+ macro(strcasecmp) \+ macro(strcat) \+ macro(strchr) \+ macro(strcmp) \+ macro(strcoll) \+ macro(strcpy) \+ macro(strcspn) \+ macro(strdup) \+ macro(strlen) \+ macro(strncasecmp) \+ macro(strncat) \+ macro(strncmp) \+ macro(strncpy) \+ macro(strndup) \+ macro(strnlen) \+ macro(strpbrk) \+ macro(strrchr) \+ macro(strspn) \+ macro(strstr) \+ macro(strtod) \+ macro(strtof) \+ macro(strtok) \+ macro(strtok_r) \+ macro(strtol) \+ macro(strtold) \+ macro(strtoll) \+ macro(strtoul) \+ macro(strtoull) \+ macro(strxfrm) \+ macro(system) \+ macro(tan) \+ macro(tanf) \+ macro(tanh) \+ macro(tanhf) \+ macro(tanhl) \+ macro(tanl) \+ macro(times) \+ macro(tmpfile) \+ macro(tmpfile64) \+ macro(toascii) \+ macro(trunc) \+ macro(truncf) \+ macro(truncl) \+ macro(uname) \+ macro(ungetc) \+ macro(unlink) \+ macro(unsetenv) \+ macro(utime) \+ macro(utimes) \+ macro(valloc) \+ macro(vfprintf) \+ macro(vfscanf) \+ macro(vprintf) \+ macro(vscanf) \+ macro(vsnprintf) \+ macro(vsprintf) \+ macro(vsscanf) \+ macro(write)++typedef enum {+#define ENUM_CASE(x) LLVMLibFunc__ ## x,+LLVM_HS_FOR_EACH_LIB_FUNC(ENUM_CASE)+#undef ENUM_CASE+} LLVMLibFunc;++#endif
+ src/LLVM/Internal/FFI/MemoryBuffer.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}+module LLVM.Internal.FFI.MemoryBuffer where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.LLVMCTypes++data MemoryBuffer++foreign import ccall unsafe "LLVMCreateMemoryBufferWithContentsOfFile" createMemoryBufferWithContentsOfFile ::+ Ptr CChar -> Ptr (Ptr MemoryBuffer) -> Ptr (OwnerTransfered CString) -> IO LLVMBool++foreign import ccall unsafe "LLVMCreateMemoryBufferWithMemoryRange" createMemoryBufferWithMemoryRange ::+ Ptr CChar -> CSize -> CString -> LLVMBool -> IO (Ptr MemoryBuffer)++foreign import ccall unsafe "LLVMGetBufferStart" getBufferStart ::+ Ptr MemoryBuffer -> IO (Ptr CChar)++foreign import ccall unsafe "LLVMGetBufferSize" getBufferSize ::+ Ptr MemoryBuffer -> IO CSize++foreign import ccall unsafe "LLVMDisposeMemoryBuffer" disposeMemoryBuffer ::+ Ptr MemoryBuffer -> IO ()
+ src/LLVM/Internal/FFI/Metadata.hpp view
@@ -0,0 +1,11 @@+#include "llvm/IR/Metadata.h"+#include "llvm-c/Core.h"++namespace llvm {+typedef struct LLVMOpaqueMetadata *LLVMMetadataRef;+DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef)++inline Metadata **unwrap(LLVMMetadataRef *Vals) {+ return reinterpret_cast<Metadata**>(Vals);+}+}
+ src/LLVM/Internal/FFI/Metadata.hs view
@@ -0,0 +1,93 @@+{-#+ LANGUAGE+ ForeignFunctionInterface+ #-}++module LLVM.Internal.FFI.Metadata where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.Context+import LLVM.Internal.FFI.PtrHierarchy+import LLVM.Internal.FFI.LLVMCTypes++foreign import ccall unsafe "LLVM_Hs_IsAMDString" isAMDString ::+ Ptr Metadata -> IO (Ptr MDString)++foreign import ccall unsafe "LLVM_Hs_IsAMDNode" isAMDNode ::+ Ptr Metadata -> IO (Ptr MDNode)++foreign import ccall unsafe "LLVM_Hs_IsAMDValue" isAMDValue ::+ Ptr Metadata -> IO (Ptr MDValue)++foreign import ccall unsafe "LLVM_Hs_IsAMetadataOperand" isAMetadataOperand ::+ Ptr Value -> IO (Ptr MetadataAsVal)++foreign import ccall unsafe "LLVM_Hs_GetMDValue" getMDValue ::+ Ptr MDValue -> IO (Ptr Value)++foreign import ccall unsafe "LLVM_Hs_GetMetadataOperand" getMetadataOperand ::+ Ptr MetadataAsVal -> IO (Ptr Metadata)++foreign import ccall unsafe "LLVMGetMDKindIDInContext" getMDKindIDInContext' ::+ Ptr Context -> Ptr CChar -> CUInt -> IO MDKindID++getMDKindIDInContext :: Ptr Context -> (Ptr CChar, CUInt) -> IO MDKindID+getMDKindIDInContext ctx (c, n) = getMDKindIDInContext' ctx c n++foreign import ccall unsafe "LLVM_Hs_GetMDKindNames" getMDKindNames ::+ Ptr Context -> Ptr (Ptr CChar) -> Ptr CUInt -> CUInt -> IO CUInt++foreign import ccall unsafe "LLVM_Hs_MDStringInContext" mdStringInContext' ::+ Ptr Context -> CString -> CUInt -> IO (Ptr MDString)++foreign import ccall unsafe "LLVM_Hs_MDValue" mdValue ::+ Ptr Value -> IO (Ptr MDValue)++foreign import ccall unsafe "LLVM_Hs_MetadataOperand" metadataOperand ::+ Ptr Context -> Ptr Metadata -> IO (Ptr Value)++mdStringInContext :: Ptr Context -> (CString, CUInt) -> IO (Ptr MDString)+mdStringInContext ctx (p, n) = mdStringInContext' ctx p n++foreign import ccall unsafe "LLVM_Hs_GetMDString" getMDString ::+ Ptr MDString -> Ptr CUInt -> IO CString++foreign import ccall unsafe "LLVM_Hs_MDNodeInContext" createMDNodeInContext' ::+ Ptr Context -> Ptr (Ptr Metadata) -> CUInt -> IO (Ptr MDNode)++createMDNodeInContext :: Ptr Context -> (CUInt, Ptr (Ptr Metadata)) -> IO (Ptr MDNode)+createMDNodeInContext ctx (n, vs) = createMDNodeInContext' ctx vs n++foreign import ccall unsafe "LLVM_Hs_CreateTemporaryMDNodeInContext" createTemporaryMDNodeInContext ::+ Ptr Context -> IO (Ptr MDNode)++foreign import ccall unsafe "LLVM_Hs_DestroyTemporaryMDNode" destroyTemporaryMDNode ::+ Ptr MDNode -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetMDNodeNumOperands" getMDNodeNumOperands ::+ Ptr MDNode -> IO CUInt++foreign import ccall unsafe "LLVM_Hs_GetMDNodeOperands" getMDNodeOperands ::+ Ptr MDNode -> Ptr (Ptr Metadata) -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetNamedMetadataName" getNamedMetadataName ::+ Ptr NamedMetadata -> Ptr CUInt -> IO (Ptr CChar)++foreign import ccall unsafe "LLVM_Hs_GetNamedMetadataNumOperands" getNamedMetadataNumOperands ::+ Ptr NamedMetadata -> IO CUInt++foreign import ccall unsafe "LLVM_Hs_GetNamedMetadataOperands" getNamedMetadataOperands ::+ Ptr NamedMetadata -> Ptr (Ptr MDNode) -> IO ()++foreign import ccall unsafe "LLVM_Hs_NamedMetadataAddOperands" namedMetadataAddOperands' ::+ Ptr NamedMetadata -> Ptr (Ptr MDNode) -> CUInt -> IO ()++foreign import ccall unsafe "LLVM_Hs_MetadataReplaceAllUsesWith" metadataReplaceAllUsesWith ::+ Ptr MDNode -> Ptr Metadata -> IO ()++namedMetadataAddOperands :: Ptr NamedMetadata -> (CUInt, Ptr (Ptr MDNode)) -> IO ()+namedMetadataAddOperands nm (n, vs) = namedMetadataAddOperands' nm vs n
+ src/LLVM/Internal/FFI/MetadataC.cpp view
@@ -0,0 +1,151 @@+#define __STDC_LIMIT_MACROS++#include <iostream>+#include "LLVM/Internal/FFI/Metadata.hpp"+#include "llvm/Support/FormattedStream.h"++#include "llvm/Config/llvm-config.h"+#include "llvm/IR/LLVMContext.h"+#include "llvm/IR/Metadata.h"+#include "llvm-c/Core.h"++using namespace llvm;++extern "C" {++LLVMMetadataRef LLVM_Hs_IsAMDString(LLVMMetadataRef md) {+ if (isa<MDString>(unwrap(md))) {+ return md;+ }+ return nullptr;+}++LLVMMetadataRef LLVM_Hs_MDStringInContext(LLVMContextRef c,+ const char *str, unsigned slen) {+ return wrap(MDString::get(*unwrap(c), StringRef(str, slen)));+}++const char *LLVM_Hs_GetMDString(LLVMMetadataRef md, unsigned* len) {+ if (const MDString *S = dyn_cast<MDString>(unwrap(md))) {+ *len = S->getString().size();+ return S->getString().data();+ }+ *len = 0;+ return nullptr;+}++LLVMMetadataRef LLVM_Hs_MDValue(LLVMValueRef v) {+ return wrap(ValueAsMetadata::get(unwrap(v)));+}++LLVMValueRef LLVM_Hs_MetadataOperand(LLVMContextRef c, LLVMMetadataRef md) {+ return wrap(MetadataAsValue::get(*unwrap(c), unwrap(md)));+}++LLVMMetadataRef LLVM_Hs_IsAMDNode(LLVMMetadataRef md) {+ if (isa<MDNode>(unwrap(md))) {+ return md;+ }+ return nullptr;+}++LLVMValueRef LLVM_Hs_GetMDValue(LLVMMetadataRef md) {+ return wrap(unwrap<ValueAsMetadata>(md)->getValue());+}++LLVMMetadataRef LLVM_Hs_GetMetadataOperand(LLVMValueRef val) {+ return wrap(unwrap<MetadataAsValue>(val)->getMetadata());+}++LLVMMetadataRef LLVM_Hs_MDNodeInContext(LLVMContextRef c,+ LLVMMetadataRef *mds,+ unsigned count) {+ return wrap(MDNode::get(*unwrap(c), ArrayRef<Metadata *>(unwrap(mds), count)));+}++LLVMMetadataRef LLVM_Hs_IsAMDValue(LLVMMetadataRef md) {+ if (isa<ValueAsMetadata>(unwrap(md))) {+ return md;+ }+ return nullptr;+}+++LLVMValueRef LLVM_Hs_IsAMetadataOperand(LLVMValueRef val) {+ if (isa<MetadataAsValue>(unwrap(val))) {+ return val;+ }+ return nullptr;+}+++unsigned LLVM_Hs_GetMDKindNames(+ LLVMContextRef c,+ const char **s,+ unsigned *l,+ unsigned n+) {+ SmallVector<StringRef, 8> ns;+ unwrap(c)->getMDKindNames(ns);+ if (ns.size() <= n) {+ for(unsigned i=0; i < ns.size(); ++i) {+ s[i] = ns[i].data();+ l[i] = ns[i].size();+ }+ }+ return ns.size();+}++unsigned LLVM_Hs_GetMDNodeNumOperands(LLVMMetadataRef v) {+ return unwrap<MDNode>(v)->getNumOperands();+}++void LLVM_Hs_NamedMetadataAddOperands(+ NamedMDNode *n,+ LLVMMetadataRef *ops,+ unsigned nOps+) {+ for(unsigned i = 0; i != nOps; ++i) n->addOperand(unwrap<MDNode>(ops[i]));+}++const char *LLVM_Hs_GetNamedMetadataName(+ NamedMDNode *n,+ unsigned *len+) {+ StringRef s = n->getName();+ *len = s.size();+ return s.data();+}++unsigned LLVM_Hs_GetNamedMetadataNumOperands(NamedMDNode *n) {+ return n->getNumOperands();+}++void LLVM_Hs_GetNamedMetadataOperands(NamedMDNode *n, LLVMMetadataRef *dest) {+ for(unsigned i = 0; i != n->getNumOperands(); ++i)+ dest[i] = wrap(n->getOperand(i));+}++LLVMMetadataRef LLVM_Hs_CreateTemporaryMDNodeInContext(LLVMContextRef c) {+ return wrap(MDNode::getTemporary(*unwrap(c), ArrayRef<Metadata *>()).release());+}++void LLVM_Hs_DestroyTemporaryMDNode(LLVMMetadataRef v) {+ MDNode::deleteTemporary(unwrap<MDNode>(v));+}++void LLVM_Hs_GetMDNodeOperands(LLVMMetadataRef md, LLVMMetadataRef *dest) {+ const auto *N = cast<MDNode>(unwrap(md));+ const unsigned numOperands = N->getNumOperands();+ for (unsigned i = 0; i < numOperands; i++)+ dest[i] = wrap(N->getOperand(i));+}++void LLVM_Hs_MetadataReplaceAllUsesWith(LLVMMetadataRef md, LLVMMetadataRef replacement) {+ auto *Node = unwrap<MDNode>(md);+ Node->replaceAllUsesWith(unwrap<Metadata>(replacement));+ MDNode::deleteTemporary(Node);+}++}+
+ src/LLVM/Internal/FFI/Module.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}+module LLVM.Internal.FFI.Module where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.Context+import LLVM.Internal.FFI.GlobalValue (COMDAT)+import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.PtrHierarchy+import LLVM.Internal.FFI.Type++data Module++foreign import ccall unsafe "LLVMModuleCreateWithNameInContext" moduleCreateWithNameInContext ::+ CString -> Ptr Context -> IO (Ptr Module)++foreign import ccall unsafe "LLVMGetModuleContext" getModuleContext ::+ Ptr Module -> IO (Ptr Context)++foreign import ccall unsafe "LLVMDisposeModule" disposeModule ::+ Ptr Module -> IO ()++foreign import ccall unsafe "LLVMGetDataLayout" getDataLayout ::+ Ptr Module -> IO CString++foreign import ccall unsafe "LLVMSetDataLayout" setDataLayout ::+ Ptr Module -> CString -> IO ()++foreign import ccall unsafe "LLVMGetTarget" getTargetTriple ::+ Ptr Module -> IO CString++foreign import ccall unsafe "LLVMSetTarget" setTargetTriple ::+ Ptr Module -> CString -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetModuleIdentifier" getModuleIdentifier ::+ Ptr Module -> IO (OwnerTransfered CString)++foreign import ccall unsafe "LLVM_Hs_GetSourceFileName" getSourceFileName ::+ Ptr Module -> IO (OwnerTransfered CString)++foreign import ccall unsafe "LLVM_Hs_SetSourceFileName" setSourceFileName ::+ Ptr Module -> Ptr CChar -> IO ()++foreign import ccall unsafe "LLVMGetFirstGlobal" getFirstGlobal ::+ Ptr Module -> IO (Ptr GlobalVariable)++foreign import ccall unsafe "LLVMGetNextGlobal" getNextGlobal ::+ Ptr GlobalVariable -> IO (Ptr GlobalVariable)++foreign import ccall unsafe "LLVM_Hs_GetFirstAlias" getFirstAlias ::+ Ptr Module -> IO (Ptr GlobalAlias)++foreign import ccall unsafe "LLVM_Hs_GetNextAlias" getNextAlias ::+ Ptr GlobalAlias -> IO (Ptr GlobalAlias)++foreign import ccall unsafe "LLVM_Hs_GetOrInsertCOMDAT" getOrInsertCOMDAT ::+ Ptr Module -> CString -> IO (Ptr COMDAT)++foreign import ccall unsafe "LLVMGetFirstFunction" getFirstFunction ::+ Ptr Module -> IO (Ptr Function)++foreign import ccall unsafe "LLVMGetNextFunction" getNextFunction ::+ Ptr Function -> IO (Ptr Function)++foreign import ccall unsafe "LLVM_Hs_GetFirstNamedMetadata" getFirstNamedMetadata ::+ Ptr Module -> IO (Ptr NamedMetadata)++foreign import ccall unsafe "LLVM_Hs_GetNextNamedMetadata" getNextNamedMetadata ::+ Ptr NamedMetadata -> IO (Ptr NamedMetadata)++foreign import ccall unsafe "LLVMAddGlobalInAddressSpace" addGlobalInAddressSpace ::+ Ptr Module -> Ptr Type -> CString -> CUInt -> IO (Ptr GlobalVariable)++foreign import ccall unsafe "LLVM_Hs_JustAddAlias" justAddAlias ::+ Ptr Module -> Ptr Type -> AddrSpace -> CString -> IO (Ptr GlobalAlias)++foreign import ccall unsafe "LLVMAddFunction" addFunction ::+ Ptr Module -> CString -> Ptr Type -> IO (Ptr Function)++foreign import ccall unsafe "LLVMGetNamedFunction" getNamedFunction ::+ Ptr Module -> CString -> IO (Ptr Function)++foreign import ccall unsafe "LLVM_Hs_GetOrAddNamedMetadata" getOrAddNamedMetadata ::+ Ptr Module -> CString -> IO (Ptr NamedMetadata)++foreign import ccall unsafe "LLVM_Hs_ModuleAppendInlineAsm" moduleAppendInlineAsm' ::+ Ptr Module -> Ptr CChar -> CUInt -> IO ()++newtype ModuleAsm a = ModuleAsm a++moduleAppendInlineAsm :: Ptr Module -> ModuleAsm (Ptr CChar, CUInt) -> IO ()+moduleAppendInlineAsm m (ModuleAsm (c, n)) = moduleAppendInlineAsm' m c n++foreign import ccall unsafe "LLVM_Hs_ModuleGetInlineAsm" moduleGetInlineAsm ::+ Ptr Module -> IO (ModuleAsm CString)++foreign import ccall unsafe "LLVMLinkModules2" linkModules ::+ Ptr Module -> Ptr Module -> IO LLVMBool
+ src/LLVM/Internal/FFI/ModuleC.cpp view
@@ -0,0 +1,70 @@+#define __STDC_LIMIT_MACROS+#include "llvm/IR/Module.h"+#include "llvm-c/Core.h"++using namespace llvm;++extern "C" {++char *LLVM_Hs_GetModuleIdentifier(LLVMModuleRef val) {+ return strdup(unwrap(val)->getModuleIdentifier().c_str());+}++char *LLVM_Hs_GetSourceFileName(LLVMModuleRef val) {+ return strdup(unwrap(val)->getSourceFileName().c_str());+}++void LLVM_Hs_SetSourceFileName(LLVMModuleRef val, const char* sourceFileName) {+ return unwrap(val)->setSourceFileName(sourceFileName);+}++LLVMValueRef LLVM_Hs_GetFirstAlias(LLVMModuleRef m) {+ Module *mod = unwrap(m);+ Module::alias_iterator i = mod->alias_begin();+ if (i == mod->alias_end()) {+ return 0;+ }+ return wrap(&*i);+}++LLVMValueRef LLVM_Hs_GetNextAlias(LLVMValueRef a) {+ GlobalAlias *alias = unwrap<GlobalAlias>(a);+ Module::alias_iterator i(alias);+ if (++i == alias->getParent()->alias_end()) return 0;+ return wrap(&*i);+}++Comdat *LLVM_Hs_GetOrInsertCOMDAT(LLVMModuleRef m, const char *name) {+ return unwrap(m)->getOrInsertComdat(name);+}++// TODO (cocreature): Figure out if we can just change the linkage here+LLVMValueRef LLVM_Hs_JustAddAlias(LLVMModuleRef m, LLVMTypeRef ty, unsigned addrspace, const char *name) {+ return wrap(GlobalAlias::create(unwrap(ty), addrspace, GlobalValue::ExternalLinkage, name, 0, unwrap(m)));+}++NamedMDNode *LLVM_Hs_GetOrAddNamedMetadata(LLVMModuleRef m, const char *name) {+ return unwrap(m)->getOrInsertNamedMetadata(name);+}++NamedMDNode *LLVM_Hs_GetFirstNamedMetadata(LLVMModuleRef m) {+ Module *mod = unwrap(m);+ Module::named_metadata_iterator i = mod->named_metadata_begin();+ return i == mod->named_metadata_end() ? 0 : &*i;+}++NamedMDNode *LLVM_Hs_GetNextNamedMetadata(NamedMDNode *a) {+ Module::named_metadata_iterator i(a);+ if (++i == a->getParent()->named_metadata_end()) return 0;+ return &*i;+}++void LLVM_Hs_ModuleAppendInlineAsm(LLVMModuleRef m, const char *s, unsigned l) {+ unwrap(m)->appendModuleInlineAsm(StringRef(s,l));+}++const char *LLVM_Hs_ModuleGetInlineAsm(LLVMModuleRef m) {+ return unwrap(m)->getModuleInlineAsm().c_str();+}++}
+ src/LLVM/Internal/FFI/OrcJIT.h view
@@ -0,0 +1,15 @@+#ifndef __LLVM_INTERNAL_FFI__ORC_JIT__H__+#define __LLVM_INTERNAL_FFI__ORC_JIT__H__++#define LLVM_HS_FOR_EACH_JIT_SYMBOL_FLAG(macro) \+ macro(None) \+ macro(Weak) \+ macro(Exported) \++typedef enum {+#define ENUM_CASE(x) LLVMJITSymbolFlag ## x,+LLVM_HS_FOR_EACH_JIT_SYMBOL_FLAG(ENUM_CASE)+#undef ENUM_CASE+} LLVMJITSymbolFlags;++#endif
+ src/LLVM/Internal/FFI/OrcJIT.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE ForeignFunctionInterface #-}++module LLVM.Internal.FFI.OrcJIT where++import LLVM.Prelude++import Foreign.C+import Foreign.Ptr++import LLVM.Internal.FFI.DataLayout+import LLVM.Internal.FFI.LLVMCTypes++data JITSymbol+data LambdaResolver+data ObjectLinkingLayer++newtype TargetAddress = TargetAddress Word64++type SymbolResolverFn = CString -> Ptr JITSymbol -> IO ()++foreign import ccall "wrapper" wrapSymbolResolverFn ::+ SymbolResolverFn -> IO (FunPtr SymbolResolverFn)++foreign import ccall safe "LLVM_Hs_disposeJITSymbol" disposeSymbol ::+ Ptr JITSymbol -> IO ()++foreign import ccall safe "LLVM_Hs_createLambdaResolver" createLambdaResolver ::+ FunPtr SymbolResolverFn ->+ FunPtr SymbolResolverFn ->+ IO (Ptr LambdaResolver)++foreign import ccall safe "LLVM_Hs_createObjectLinkingLayer" createObjectLinkingLayer ::+ IO (Ptr ObjectLinkingLayer)++foreign import ccall safe "LLVM_Hs_disposeObjectLinkingLayer" disposeObjectLinkingLayer ::+ Ptr ObjectLinkingLayer -> IO ()++foreign import ccall safe "LLVM_Hs_JITSymbol_getAddress" getAddress ::+ Ptr JITSymbol -> IO TargetAddress++foreign import ccall safe "LLVM_Hs_JITSymbol_getFlags" getFlags ::+ Ptr JITSymbol -> IO JITSymbolFlags++foreign import ccall safe "LLVM_Hs_setJITSymbol" setJITSymbol ::+ Ptr JITSymbol -> TargetAddress -> JITSymbolFlags -> IO ()++foreign import ccall safe "LLVM_Hs_getMangledSymbol" getMangledSymbol ::+ Ptr CString -> CString -> Ptr DataLayout -> IO ()++foreign import ccall safe "LLVM_Hs_disposeMangledSymbol" disposeMangledSymbol ::+ CString -> IO ()
+ src/LLVM/Internal/FFI/OrcJIT/CompileOnDemandLayer.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module LLVM.Internal.FFI.OrcJIT.CompileOnDemandLayer where++import LLVM.Prelude++import Foreign.C+import Foreign.Ptr++import LLVM.Internal.FFI.DataLayout+import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.Module+import LLVM.Internal.FFI.OrcJIT+import LLVM.Internal.FFI.OrcJIT.IRCompileLayer (IRCompileLayer)+import LLVM.Internal.FFI.PtrHierarchy++data IndirectStubsManagerBuilder+data JITCompileCallbackManager+data CompileOnDemandLayer+data Set a+data ModuleSetHandle++type PartitioningFn = Ptr Function -> Ptr (Set (Ptr Function)) -> IO ()++foreign import ccall "wrapper" wrapPartitioningFn ::+ PartitioningFn -> IO (FunPtr PartitioningFn)++foreign import ccall "wrapper" wrapErrorHandler ::+ IO () -> IO (FunPtr (IO ()))++foreign import ccall safe "LLVM_Hs_createLocalCompileCallbackManager" createLocalCompileCallbackManager ::+ CString -> TargetAddress -> IO (Ptr JITCompileCallbackManager)++foreign import ccall safe "LLVM_Hs_disposeCallbackManager" disposeCallbackManager ::+ Ptr JITCompileCallbackManager -> IO ()++foreign import ccall safe "LLVM_Hs_createLocalIndirectStubsManagerBuilder" createLocalIndirectStubsManagerBuilder ::+ CString -> IO (Ptr IndirectStubsManagerBuilder)++foreign import ccall safe "LLVM_Hs_disposeIndirectStubsManagerBuilder" disposeIndirectStubsManagerBuilder ::+ Ptr IndirectStubsManagerBuilder -> IO ()++foreign import ccall safe "LLVM_Hs_insertFun" insertFun ::+ Ptr (Set (Ptr Function)) -> Ptr Function -> IO ()++foreign import ccall safe "LLVM_Hs_createCompileOnDemandLayer" createCompileOnDemandLayer ::+ Ptr IRCompileLayer ->+ FunPtr PartitioningFn ->+ Ptr JITCompileCallbackManager ->+ Ptr IndirectStubsManagerBuilder ->+ LLVMBool ->+ IO (Ptr CompileOnDemandLayer)++foreign import ccall safe "LLVM_Hs_disposeCompileOnDemandLayer" disposeCompileOnDemandLayer ::+ Ptr CompileOnDemandLayer ->+ IO ()++foreign import ccall safe "LLVM_Hs_CompileOnDemandLayer_addModuleSet" addModuleSet ::+ Ptr CompileOnDemandLayer ->+ Ptr DataLayout ->+ Ptr (Ptr Module) ->+ CUInt ->+ Ptr LambdaResolver ->+ IO (Ptr ModuleSetHandle)++foreign import ccall safe "LLVM_Hs_CompileOnDemandLayer_removeModuleSet" removeModuleSet ::+ Ptr CompileOnDemandLayer ->+ Ptr ModuleSetHandle ->+ IO ()++foreign import ccall safe "LLVM_Hs_CompileOnDemandLayer_findSymbol" findSymbol ::+ Ptr CompileOnDemandLayer ->+ CString ->+ LLVMBool ->+ IO (Ptr JITSymbol)
+ src/LLVM/Internal/FFI/OrcJIT/IRCompileLayer.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module LLVM.Internal.FFI.OrcJIT.IRCompileLayer where++import LLVM.Prelude++import LLVM.Internal.FFI.DataLayout+import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.Module+import LLVM.Internal.FFI.OrcJIT+import LLVM.Internal.FFI.Target++import Foreign.Ptr+import Foreign.C++data IRCompileLayer+data ModuleSetHandle++foreign import ccall safe "LLVM_Hs_createIRCompileLayer" createIRCompileLayer ::+ Ptr ObjectLinkingLayer -> Ptr TargetMachine -> IO (Ptr IRCompileLayer)++foreign import ccall safe "LLVM_Hs_disposeIRCompileLayer" disposeIRCompileLayer ::+ Ptr IRCompileLayer -> IO ()++foreign import ccall safe "LLVM_Hs_IRCompileLayer_addModuleSet" addModuleSet ::+ Ptr IRCompileLayer ->+ Ptr DataLayout ->+ Ptr (Ptr Module) ->+ CUInt ->+ Ptr LambdaResolver ->+ IO (Ptr ModuleSetHandle)++foreign import ccall safe "LLVM_Hs_IRCompileLayer_removeModuleSet" removeModuleSet ::+ Ptr IRCompileLayer -> Ptr ModuleSetHandle -> IO ()++foreign import ccall safe "LLVM_Hs_IRCompileLayer_findSymbol" findSymbol ::+ Ptr IRCompileLayer -> CString -> LLVMBool -> IO (Ptr JITSymbol)
+ src/LLVM/Internal/FFI/OrcJITC.cpp view
@@ -0,0 +1,256 @@+#include "LLVM/Internal/FFI/OrcJIT.h"+#include "LLVM/Internal/FFI/Target.hpp"+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"+#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"+#include "llvm/ExecutionEngine/JITSymbol.h"+#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"+#include "llvm/IR/Mangler.h"++#include <type_traits>++using namespace llvm;+using namespace orc;++typedef llvm::orc::ObjectLinkingLayer<> *LLVMObjectLinkingLayerRef;+typedef llvm::orc::IRCompileLayer<llvm::orc::ObjectLinkingLayer<>>+ LLVMIRCompileLayer;+typedef LLVMIRCompileLayer *LLVMIRCompileLayerRef;+typedef llvm::orc::CompileOnDemandLayer<LLVMIRCompileLayer>+ LLVMCompileOnDemandLayer;+typedef LLVMCompileOnDemandLayer *LLVMCompileOnDemandLayerRef;+typedef llvm::orc::JITCompileCallbackManager *LLVMJITCompileCallbackManagerRef;+typedef llvm::JITSymbol *LLVMJITSymbolRef;+typedef LLVMIRCompileLayer::ModuleSetHandleT *LLVMModuleSetHandleRef;+typedef LLVMCompileOnDemandLayer::ModuleSetHandleT *LLVMCODModuleSetHandleRef;+typedef llvm::orc::LambdaResolver<+ std::function<JITSymbol(const std::string &name)>,+ std::function<JITSymbol(const std::string &name)>>+ LLVMLambdaResolver;+typedef LLVMLambdaResolver *LLVMLambdaResolverRef;+typedef llvm::orc::IndirectStubsManager *LLVMIndirectStubsManagerRef;+typedef std::function<std::unique_ptr<llvm::orc::IndirectStubsManager>()>+ *LLVMIndirectStubsManagerBuilderRef;++static std::string mangle(StringRef name, LLVMTargetDataRef dataLayout) {+ std::string mangledName;+ {+ raw_string_ostream mangledNameStream(mangledName);+ Mangler::getNameWithPrefix(mangledNameStream, name,+ *unwrap(dataLayout));+ }+ return mangledName;+}++static std::vector<Module *> getModules(LLVMModuleRef *modules,+ unsigned moduleCount,+ LLVMTargetDataRef dataLayout) {+ std::vector<Module *> moduleVec(moduleCount);+ for (unsigned i = 0; i < moduleCount; ++i) {+ moduleVec.at(i) = unwrap(modules[i]);+ if (moduleVec.at(i)->getDataLayout().isDefault()) {+ moduleVec.at(i)->setDataLayout(*unwrap(dataLayout));+ }+ }+ return moduleVec;+}++extern "C" {+LLVMIRCompileLayerRef+LLVM_Hs_createIRCompileLayer(LLVMObjectLinkingLayerRef objectLayer,+ LLVMTargetMachineRef tm) {+ TargetMachine *tmm = unwrap(tm);+ return new IRCompileLayer<ObjectLinkingLayer<>>(*objectLayer,+ SimpleCompiler(*tmm));+}++void LLVM_Hs_disposeIRCompileLayer(LLVMIRCompileLayerRef compileLayer) {+ delete compileLayer;+}++LLVMJITSymbolRef+LLVM_Hs_IRCompileLayer_findSymbol(LLVMIRCompileLayerRef compileLayer,+ const char *name,+ LLVMBool exportedSymbolsOnly) {+ JITSymbol symbol = compileLayer->findSymbol(name, exportedSymbolsOnly);+ return new JITSymbol(symbol);+}++void LLVM_Hs_disposeJITSymbol(LLVMJITSymbolRef symbol) { delete symbol; }++LLVMLambdaResolverRef LLVM_Hs_createLambdaResolver(+ void (*dylibResolver)(const char *, LLVMJITSymbolRef),+ void (*externalResolver)(const char *, LLVMJITSymbolRef)) {+ std::function<JITSymbol(const std::string &name)>+ dylibResolverFun = [dylibResolver](+ const std::string &name) -> JITSymbol {+ JITSymbol symbol(nullptr);+ dylibResolver(name.c_str(), &symbol);+ return symbol;+ };+ std::function<JITSymbol(const std::string &name)>+ externalResolverFun = [externalResolver](+ const std::string &name) -> JITSymbol {+ JITSymbol symbol(nullptr);+ externalResolver(name.c_str(), &symbol);+ return symbol;+ };+ auto lambdaResolver =+ createLambdaResolver(dylibResolverFun, externalResolverFun);+ return lambdaResolver.release();+}++LLVMModuleSetHandleRef LLVM_Hs_IRCompileLayer_addModuleSet(+ LLVMIRCompileLayerRef compileLayer, LLVMTargetDataRef dataLayout,+ LLVMModuleRef *modules, unsigned moduleCount,+ LLVMLambdaResolverRef resolver) {+ std::vector<Module *> moduleVec =+ getModules(modules, moduleCount, dataLayout);+ return new IRCompileLayer<ObjectLinkingLayer<>>::ModuleSetHandleT(+ compileLayer->addModuleSet(+ moduleVec, make_unique<SectionMemoryManager>(), resolver));+}++void LLVM_Hs_IRCompileLayer_removeModuleSet(+ LLVMIRCompileLayerRef compileLayer,+ LLVMModuleSetHandleRef moduleSetHandle) {+ compileLayer->removeModuleSet(*moduleSetHandle);+ delete moduleSetHandle;+}++LLVMObjectLinkingLayerRef LLVM_Hs_createObjectLinkingLayer() {+ return new ObjectLinkingLayer<>();+}++void LLVM_Hs_disposeObjectLinkingLayer(+ LLVMObjectLinkingLayerRef objectLayer) {+ delete objectLayer;+}++static JITSymbolFlags unwrap(LLVMJITSymbolFlags f) {+ JITSymbolFlags flags = JITSymbolFlags::None;+#define ENUM_CASE(x) \+ if (f & LLVMJITSymbolFlag##x) \+ flags |= JITSymbolFlags::x;+ LLVM_HS_FOR_EACH_JIT_SYMBOL_FLAG(ENUM_CASE)+#undef ENUM_CASE+ return flags;+}++static LLVMJITSymbolFlags wrap(JITSymbolFlags f) {+ unsigned r = 0;+#define ENUM_CASE(x) \+ if ((char)(f & JITSymbolFlags::x)) \+ r |= (unsigned)LLVMJITSymbolFlag##x;+ LLVM_HS_FOR_EACH_JIT_SYMBOL_FLAG(ENUM_CASE)+#undef ENUM_CASE+ return LLVMJITSymbolFlags(r);+}++JITTargetAddress+LLVM_Hs_JITSymbol_getAddress(LLVMJITSymbolRef symbol) {+ return symbol->getAddress();+}++LLVMJITSymbolFlags LLVM_Hs_JITSymbol_getFlags(LLVMJITSymbolRef symbol) {+ return wrap(symbol->getFlags());+}++void LLVM_Hs_setJITSymbol(LLVMJITSymbolRef symbol,+ JITTargetAddress addr,+ LLVMJITSymbolFlags flags) {+ *symbol = JITSymbol(addr, unwrap(flags));+}++void LLVM_Hs_getMangledSymbol(char **mangledSymbol, const char *symbol,+ LLVMTargetDataRef dataLayout) {+ std::string mangled = mangle(symbol, dataLayout);+ *mangledSymbol = new char[mangled.size() + 1];+ strcpy(*mangledSymbol, mangled.c_str());+}++void LLVM_Hs_disposeMangledSymbol(char *mangledSymbol) {+ delete[] mangledSymbol;+}++LLVMJITCompileCallbackManagerRef LLVM_Hs_createLocalCompileCallbackManager(+ const char *triple, JITTargetAddress errorHandler) {+ return llvm::orc::createLocalCompileCallbackManager(Triple(triple),+ errorHandler)+ .release();+}++void LLVM_Hs_disposeCallbackManager(+ LLVMJITCompileCallbackManagerRef callbackManager) {+ delete callbackManager;+}++LLVMIndirectStubsManagerBuilderRef+LLVM_Hs_createLocalIndirectStubsManagerBuilder(const char *triple) {+ return new std::function<std::unique_ptr<IndirectStubsManager>()>(+ llvm::orc::createLocalIndirectStubsManagerBuilder(Triple(triple)));+}++void LLVM_Hs_disposeIndirectStubsManagerBuilder(+ LLVMIndirectStubsManagerBuilderRef stubsManager) {+ delete stubsManager;+}++void LLVM_Hs_insertFun(std::set<llvm::Function *> *set,+ llvm::Function *f) {+ set->insert(f);+}++LLVMCompileOnDemandLayerRef LLVM_Hs_createCompileOnDemandLayer(+ LLVMIRCompileLayerRef compileLayer,+ void (*partitioningFtor)(llvm::Function *, std::set<llvm::Function *> *set),+ LLVMJITCompileCallbackManagerRef callbackManager,+ LLVMIndirectStubsManagerBuilderRef stubsManager,+ LLVMBool cloneStubsIntoPartitions) {+ return new LLVMCompileOnDemandLayer(+ *compileLayer,+ [partitioningFtor](llvm::Function &f) -> std::set<llvm::Function *> {+ std::set<llvm::Function *> result;+ partitioningFtor(&f, &result);+ return result;+ },+ *callbackManager, *stubsManager, cloneStubsIntoPartitions);+}++void LLVM_Hs_disposeCompileOnDemandLayer(+ LLVMCompileOnDemandLayerRef codLayer) {+ delete codLayer;+}++LLVMCODModuleSetHandleRef LLVM_Hs_CompileOnDemandLayer_addModuleSet(+ LLVMCompileOnDemandLayerRef compileLayer, LLVMTargetDataRef dataLayout,+ LLVMModuleRef *modules, unsigned moduleCount,+ LLVMLambdaResolverRef resolver) {+ std::vector<Module *> moduleVec =+ getModules(modules, moduleCount, dataLayout);+ // We need to copy the resolver to make the use of unique_ptr (required by+ // the LLVM API) safe+ std::unique_ptr<LLVMLambdaResolver> uniqueResolver(+ new LLVMLambdaResolver(*resolver));+ return new LLVMCompileOnDemandLayer::ModuleSetHandleT(+ compileLayer->addModuleSet(moduleVec,+ make_unique<SectionMemoryManager>(),+ std::move(uniqueResolver)));+}++void LLVM_Hs_CompileOnDemandLayer_removeModuleSet(+ LLVMCompileOnDemandLayerRef compileLayer,+ LLVMCODModuleSetHandleRef moduleSetHandle) {+ compileLayer->removeModuleSet(*moduleSetHandle);+ delete moduleSetHandle;+}++LLVMJITSymbolRef LLVM_Hs_CompileOnDemandLayer_findSymbol(+ LLVMCompileOnDemandLayerRef compileLayer, const char *name,+ LLVMBool exportedSymbolsOnly) {+ JITSymbol symbol = compileLayer->findSymbol(name, exportedSymbolsOnly);+ return new JITSymbol(symbol);+}+}
+ src/LLVM/Internal/FFI/PassManager.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE+ TemplateHaskell,+ ForeignFunctionInterface,+ CPP+ #-}++module LLVM.Internal.FFI.PassManager where++import LLVM.Prelude++import qualified Language.Haskell.TH as TH++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.PtrHierarchy+import LLVM.Internal.FFI.Cleanup+import LLVM.Internal.FFI.Module+import LLVM.Internal.FFI.Target+import LLVM.Internal.FFI.Transforms++import qualified LLVM.Transforms as G++data PassManager++foreign import ccall unsafe "LLVMCreatePassManager" createPassManager ::+ IO (Ptr PassManager)++foreign import ccall unsafe "LLVMDisposePassManager" disposePassManager ::+ Ptr PassManager -> IO ()++foreign import ccall unsafe "LLVMRunPassManager" runPassManager ::+ Ptr PassManager -> Ptr Module -> IO CUInt++foreign import ccall unsafe "LLVMCreateFunctionPassManagerForModule" createFunctionPassManagerForModule ::+ Ptr Module -> IO (Ptr PassManager)++foreign import ccall unsafe "LLVMInitializeFunctionPassManager" initializeFunctionPassManager ::+ Ptr PassManager -> IO CUInt++foreign import ccall unsafe "LLVMRunFunctionPassManager" runFunctionPassManager ::+ Ptr PassManager -> Ptr Value -> IO CUInt++foreign import ccall unsafe "LLVMFinalizeFunctionPassManager" finalizeFunctionPassManager ::+ Ptr PassManager -> IO CUInt++foreign import ccall unsafe "LLVMAddAnalysisPasses" addAnalysisPasses ::+ Ptr TargetMachine -> Ptr PassManager -> IO ()++foreign import ccall unsafe "LLVMAddTargetLibraryInfo" addTargetLibraryInfoPass' ::+ Ptr TargetLibraryInfo -> Ptr PassManager -> IO ()++addTargetLibraryInfoPass :: Ptr PassManager -> Ptr TargetLibraryInfo -> IO ()+addTargetLibraryInfoPass = flip addTargetLibraryInfoPass'++$(do+ let declareForeign :: TH.Name -> [TH.Type] -> TH.DecsQ+ declareForeign hName extraParams = do+ let n = TH.nameBase hName+ passTypeMapping :: TH.Type -> TH.TypeQ+ passTypeMapping t = case t of+ TH.ConT h | h == ''Word -> [t| CUInt |]+ | h == ''G.GCOVVersion -> [t| CString |]+ -- some of the LLVM methods for making passes use "-1" as a special value+ -- handle those here+ TH.AppT (TH.ConT mby) t' | mby == ''Maybe ->+ case t' of+ TH.ConT h | h == ''Bool -> [t| NothingAsMinusOne Bool |]+ | h == ''Word -> [t| NothingAsMinusOne Word |]+ | h == ''FilePath -> [t| NothingAsEmptyString CString |]+ _ -> typeMapping t+ _ -> typeMapping t+ foreignDecl+ (cName n)+ ("add" ++ n ++ "Pass")+ ([[t| Ptr PassManager |]]+ ++ [[t| Ptr TargetMachine |] | needsTargetMachine n]+ ++ map passTypeMapping extraParams)+ (TH.tupleT 0)+#if __GLASGOW_HASKELL__ < 800+ TH.TyConI (TH.DataD _ _ _ cons _) <- TH.reify ''G.Pass+#else+ TH.TyConI (TH.DataD _ _ _ _ cons _) <- TH.reify ''G.Pass+#endif+ liftM concat $ forM cons $ \con -> case con of+ TH.RecC n l -> declareForeign n [ t | (_,_,t) <- l ]+ TH.NormalC n [] -> declareForeign n []+ TH.NormalC n _ -> error "pass descriptor constructors with fields need to be records"+ )++data PassManagerBuilder++foreign import ccall unsafe "LLVMPassManagerBuilderCreate" passManagerBuilderCreate ::+ IO (Ptr PassManagerBuilder)++foreign import ccall unsafe "LLVMPassManagerBuilderDispose" passManagerBuilderDispose ::+ Ptr PassManagerBuilder -> IO ()++foreign import ccall unsafe "LLVMPassManagerBuilderSetOptLevel" passManagerBuilderSetOptLevel ::+ Ptr PassManagerBuilder -> CUInt -> IO ()++foreign import ccall unsafe "LLVMPassManagerBuilderSetSizeLevel" passManagerBuilderSetSizeLevel ::+ Ptr PassManagerBuilder -> CUInt -> IO ()++foreign import ccall unsafe "LLVMPassManagerBuilderSetDisableUnitAtATime" passManagerBuilderSetDisableUnitAtATime ::+ Ptr PassManagerBuilder -> LLVMBool -> IO ()++foreign import ccall unsafe "LLVMPassManagerBuilderSetDisableUnrollLoops" passManagerBuilderSetDisableUnrollLoops ::+ Ptr PassManagerBuilder -> CUInt -> IO ()++foreign import ccall unsafe "LLVMPassManagerBuilderSetDisableSimplifyLibCalls" passManagerBuilderSetDisableSimplifyLibCalls ::+ Ptr PassManagerBuilder -> LLVMBool -> IO ()++foreign import ccall unsafe "LLVMPassManagerBuilderUseInlinerWithThreshold" passManagerBuilderUseInlinerWithThreshold ::+ Ptr PassManagerBuilder -> CUInt -> IO ()++foreign import ccall unsafe "LLVMPassManagerBuilderPopulateFunctionPassManager" passManagerBuilderPopulateFunctionPassManager ::+ Ptr PassManagerBuilder -> Ptr PassManager -> IO ()++foreign import ccall unsafe "LLVMPassManagerBuilderPopulateModulePassManager" passManagerBuilderPopulateModulePassManager ::+ Ptr PassManagerBuilder -> Ptr PassManager -> IO ()++foreign import ccall unsafe "LLVMPassManagerBuilderPopulateLTOPassManager" passManagerBuilderPopulateLTOPassManager ::+ Ptr PassManagerBuilder -> Ptr PassManager -> CUChar -> CUChar -> IO ()++foreign import ccall unsafe "LLVM_Hs_PassManagerBuilderSetLibraryInfo" passManagerBuilderSetLibraryInfo ::+ Ptr PassManagerBuilder -> Ptr TargetLibraryInfo -> IO ()++foreign import ccall unsafe "LLVM_Hs_PassManagerBuilderSetLoopVectorize" passManagerBuilderSetLoopVectorize ::+ Ptr PassManagerBuilder -> LLVMBool -> IO ()++foreign import ccall unsafe "LLVM_Hs_PassManagerBuilderSetSuperwordLevelParallelismVectorize" passManagerBuilderSetSuperwordLevelParallelismVectorize ::+ Ptr PassManagerBuilder -> LLVMBool -> IO ()
+ src/LLVM/Internal/FFI/PassManagerC.cpp view
@@ -0,0 +1,248 @@+#define __STDC_LIMIT_MACROS+#include "llvm/IR/LLVMContext.h"+#include "llvm/IR/DataLayout.h"+#include "llvm/IR/LegacyPassManager.h"+#include "llvm/Transforms/Scalar.h"+#include "llvm/Transforms/Scalar/GVN.h"+#include "llvm/Transforms/IPO.h"+#include "llvm/Transforms/IPO/Internalize.h"+#include "llvm/Transforms/IPO/PassManagerBuilder.h"+#include "llvm/Transforms/Vectorize.h"+#include "llvm/Transforms/Instrumentation.h"+#include "llvm/CodeGen/Passes.h"+#include "llvm-c/Target.h"+#include "llvm-c/Transforms/PassManagerBuilder.h"+#include "llvm/Analysis/TargetLibraryInfo.h"+#include "llvm/Target/TargetMachine.h"++#include "llvm-c/Core.h"++using namespace llvm;++extern "C" {+typedef struct LLVMOpaqueVectorizationConfig *LLVMVectorizationConfigRef;+typedef struct LLVMOpaqueTargetLowering *LLVMTargetLoweringRef;+typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;+}++namespace llvm {+inline TargetLowering *unwrap(LLVMTargetLoweringRef P) { + return reinterpret_cast<TargetLowering *>(P);+}++inline LLVMTargetLoweringRef wrap(const TargetLowering *P) { + return reinterpret_cast<LLVMTargetLoweringRef>(const_cast<TargetLowering *>(P));+}++inline TargetMachine *unwrap(LLVMTargetMachineRef P) {+ return reinterpret_cast<TargetMachine*>(P);+}++inline LLVMTargetMachineRef wrap(const TargetMachine *P) {+ return reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine *>(P));+}++// Taken from llvm/lib/Transforms/IPO/PassManagerBuilder.cpp+inline PassManagerBuilder *unwrap(LLVMPassManagerBuilderRef P) {+ return reinterpret_cast<PassManagerBuilder*>(P);+}++inline TargetLibraryInfoImpl *unwrap(LLVMTargetLibraryInfoRef P) {+ return reinterpret_cast<TargetLibraryInfoImpl*>(P);+}++}++extern "C" {++#define LLVM_HS_FOR_EACH_PASS_WITHOUT_LLVM_C_BINDING(macro) \+ macro(BreakCriticalEdges) \+ macro(DeadCodeElimination) \+ macro(DeadInstElimination) \+ macro(DemoteRegisterToMemory) \+ macro(LCSSA) \+ macro(LoopInstSimplify) \+ macro(LowerAtomic) \+ macro(LowerSwitch) \+ macro(MergeFunctions) \+ macro(PartialInlining) \+ macro(Sinking) \+ macro(StripDeadDebugInfo) \+ macro(StripDebugDeclare) \+ macro(StripNonDebugSymbols) \++#define ENUM_CASE(p) \+void LLVM_Hs_Add ## p ## Pass(LLVMPassManagerRef PM) { \+ unwrap(PM)->add(create ## p ## Pass()); \+}+LLVM_HS_FOR_EACH_PASS_WITHOUT_LLVM_C_BINDING(ENUM_CASE)+#undef ENUM_CASE++void LLVM_Hs_AddCodeGenPreparePass(LLVMPassManagerRef PM, LLVMTargetMachineRef T) {+ unwrap(PM)->add(createCodeGenPreparePass(unwrap(T)));+}+ +void LLVM_Hs_AddGlobalValueNumberingPass(LLVMPassManagerRef PM, LLVMBool noLoads) {+ unwrap(PM)->add(createGVNPass(noLoads));+}++void LLVM_Hs_AddInternalizePass(LLVMPassManagerRef PM, unsigned nExports, const char **exports) {+ std::vector<std::string> exportList(nExports);+ for (unsigned i = 0; i < nExports; ++i) {+ exportList.at(i) = exports[i];+ }+ std::function<bool(const GlobalValue &)> mustPreserveGV = [exportList](const GlobalValue & gv) {+ for (const auto& exp : exportList) {+ if (gv.getName().equals(exp)) {+ return true;+ }+ }+ return false;+ };+ unwrap(PM)->add(createInternalizePass(std::move(mustPreserveGV)));+}++void LLVM_Hs_AddLoopStrengthReducePass(LLVMPassManagerRef PM) {+ unwrap(PM)->add(createLoopStrengthReducePass());+}++void LLVM_Hs_AddLowerInvokePass(LLVMPassManagerRef PM) {+ unwrap(PM)->add(createLowerInvokePass());+}+ +void LLVM_Hs_AddSROAPass(LLVMPassManagerRef PM) {+ unwrap(PM)->add(createSROAPass());+}++void LLVM_Hs_AddBasicBlockVectorizePass(+ LLVMPassManagerRef PM,+ unsigned vectorBits,+ LLVMBool vectorizeBools,+ LLVMBool vectorizeInts,+ LLVMBool vectorizeFloats,+ LLVMBool vectorizePointers,+ LLVMBool vectorizeCasts,+ LLVMBool vectorizeMath,+ LLVMBool vectorizeFusedMultiplyAdd,+ LLVMBool vectorizeSelect,+ LLVMBool vectorizeCmp,+ LLVMBool vectorizeGetElementPtr,+ LLVMBool vectorizeMemoryOperations,+ LLVMBool alignedOnly,+ unsigned reqChainDepth,+ unsigned searchLimit,+ unsigned maxCandidatePairsForCycleCheck,+ LLVMBool splatBreaksChain,+ unsigned maxInstructions,+ unsigned maxIterations,+ LLVMBool powerOfTwoLengthsOnly,+ LLVMBool noMemoryOperationBoost,+ LLVMBool fastDependencyAnalysis+) {+ VectorizeConfig vectorizeConfig;+ vectorizeConfig.VectorBits = vectorBits;+ vectorizeConfig.VectorizeBools = vectorizeBools;+ vectorizeConfig.VectorizeInts = vectorizeInts;+ vectorizeConfig.VectorizeFloats = vectorizeFloats;+ vectorizeConfig.VectorizePointers = vectorizePointers;+ vectorizeConfig.VectorizeCasts = vectorizeCasts;+ vectorizeConfig.VectorizeMath = vectorizeMath;+ vectorizeConfig.VectorizeFMA = vectorizeFusedMultiplyAdd;+ vectorizeConfig.VectorizeSelect = vectorizeSelect;+ vectorizeConfig.VectorizeCmp = vectorizeCmp;+ vectorizeConfig.VectorizeGEP = vectorizeGetElementPtr;+ vectorizeConfig.VectorizeMemOps = vectorizeMemoryOperations;+ vectorizeConfig.AlignedOnly = alignedOnly;+ vectorizeConfig.ReqChainDepth = reqChainDepth;+ vectorizeConfig.SearchLimit = searchLimit;+ vectorizeConfig.MaxCandPairsForCycleCheck = maxCandidatePairsForCycleCheck;+ vectorizeConfig.SplatBreaksChain = splatBreaksChain;+ vectorizeConfig.MaxInsts = maxInstructions;+ vectorizeConfig.MaxIter = maxIterations;+ vectorizeConfig.Pow2LenOnly = powerOfTwoLengthsOnly;+ vectorizeConfig.NoMemOpBoost = noMemoryOperationBoost;+ vectorizeConfig.FastDep = fastDependencyAnalysis; ++ unwrap(PM)->add(createBBVectorizePass(vectorizeConfig));+}++void LLVM_Hs_AddGCOVProfilerPass(+ LLVMPassManagerRef PM,+ LLVMBool emitNotes,+ LLVMBool emitData,+ const char *version,+ LLVMBool useCfgChecksum,+ LLVMBool noRedZone,+ LLVMBool functionNamesInData+) {+ struct GCOVOptions options;+ options.EmitNotes = emitNotes;+ options.EmitData = emitData;+ std::copy(version, version+4, options.Version);+ options.UseCfgChecksum = useCfgChecksum;+ options.NoRedZone = noRedZone;+ options.FunctionNamesInData = functionNamesInData;+ unwrap(PM)->add(createGCOVProfilerPass(options));+}++void LLVM_Hs_AddAddressSanitizerFunctionPass(+ LLVMPassManagerRef PM+) {+ unwrap(PM)->add(createAddressSanitizerFunctionPass());+}++void LLVM_Hs_AddAddressSanitizerModulePass(+ LLVMPassManagerRef PM+) {+ unwrap(PM)->add(createAddressSanitizerModulePass());+}++void LLVM_Hs_AddMemorySanitizerPass(+ LLVMPassManagerRef PM,+ LLVMBool trackOrigins+) {+ unwrap(PM)->add(createMemorySanitizerPass(trackOrigins));+}++void LLVM_Hs_AddThreadSanitizerPass(+ LLVMPassManagerRef PM+) {+ unwrap(PM)->add(createThreadSanitizerPass());+}++void LLVM_Hs_AddBoundsCheckingPass(LLVMPassManagerRef PM) {+ unwrap(PM)->add(createBoundsCheckingPass());+}++void LLVM_Hs_AddLoopVectorizePass(+ LLVMPassManagerRef PM,+ LLVMBool noUnrolling,+ LLVMBool alwaysVectorize+) {+ unwrap(PM)->add(createLoopVectorizePass(noUnrolling, alwaysVectorize));+}++void LLVM_Hs_PassManagerBuilderSetLibraryInfo(+ LLVMPassManagerBuilderRef PMB,+ LLVMTargetLibraryInfoRef l+) {+ // The PassManager frees the TargetLibraryInfo when done,+ // but we also free our ref, so give it a new copy.+ unwrap(PMB)->LibraryInfo = new TargetLibraryInfoImpl(*unwrap(l));+}++void LLVM_Hs_PassManagerBuilderSetLoopVectorize(+ LLVMPassManagerBuilderRef PMB,+ LLVMBool runLoopVectorization+) {+ unwrap(PMB)->LoopVectorize = runLoopVectorization;+}++void LLVM_Hs_PassManagerBuilderSetSuperwordLevelParallelismVectorize(+ LLVMPassManagerBuilderRef PMB,+ LLVMBool runSLPVectorization+) {+ unwrap(PMB)->SLPVectorize = runSLPVectorization;+}++}
+ src/LLVM/Internal/FFI/PtrHierarchy.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE+ ForeignFunctionInterface,+ MultiParamTypeClasses,+ FunctionalDependencies,+ UndecidableInstances,+ CPP+ #-}+#if __GLASGOW_HASKELL__ < 710+{-# LANGUAGE OverlappingInstances #-}+#define CPP_OVERLAPPING+#else+#define CPP_OVERLAPPING {-# OVERLAPPING #-}+#endif+-- | This module defines typeclasses to represent the relationships of an object-oriented inheritance hierarchy+module LLVM.Internal.FFI.PtrHierarchy where++import LLVM.Prelude++import Foreign.Ptr++-- | a class to represent safe casting of pointers to objects of descendant-classes to ancestor-classes.+class DescendentOf a b where+ upCast :: Ptr b -> Ptr a+ upCast = castPtr++-- | trivial casts+instance CPP_OVERLAPPING DescendentOf a a where+ upCast = id++-- | a class to represent direct parent-child relationships+class ChildOf b c | c -> b++-- | ancestor-descentant relationships are build out of parent-child relationships+instance (DescendentOf a b, ChildOf b c) => DescendentOf a c++-- | <http://llvm.org/doxygen/classllvm_1_1Value.html>+data Value++-- | <http://llvm.org/doxygen/classllvm_1_1Constant.html>+data Constant++instance ChildOf User Constant++-- | <http://llvm.org/doxygen/classllvm_1_1GlobalValue.html>+data GlobalValue++instance ChildOf Constant GlobalValue++-- | <http://llvm.org/doxygen/classllvm_1_1GlobalObject.html>+data GlobalObject++instance ChildOf GlobalValue GlobalObject++-- | <http://llvm.org/doxygen/classllvm_1_1GlobalVariable.html>+data GlobalVariable++instance ChildOf GlobalObject GlobalVariable++-- | <http://llvm.org/doxygen/classllvm_1_1GlobalAlias.html>+data GlobalAlias++instance ChildOf GlobalValue GlobalAlias++-- | <http://llvm.org/doxygen/classllvm_1_1Function.html>+data Function++instance ChildOf GlobalObject Function++-- | <http://llvm.org/doxygen/classllvm_1_1BasicBlock.html>+data BasicBlock++instance ChildOf Value BasicBlock++-- | <http://llvm.org/doxygen/classllvm_1_1Argument.html>+data Parameter++instance ChildOf Value Parameter++-- | <http://llvm.org/doxygen/classllvm_1_1Instruction.html>+data Instruction++instance ChildOf User Instruction++-- | <http://llvm.org/doxygen/classllvm_1_1BinaryOperator.html>+data BinaryOperator++instance ChildOf Instruction BinaryOperator++-- | <http://llvm.org/doxygen/classllvm_1_1User.html>+data User++instance ChildOf Value User++-- | <http://llvm.org/doxygen/classllvm_1_1MDNode.html>+data MDNode++instance ChildOf Metadata MDNode++-- | <http://llvm.org/doxygen/classllvm_1_1MDString.html>+data MDString++instance ChildOf Metadata MDString++-- | http://llvm.org/doxygen/classllvm_1_1ValueAsMetadata.html+data MDValue++instance ChildOf Metadata MDValue++-- | <http://llvm.org/doxygen/classllvm_1_1NamedMDNode.html>+data NamedMetadata++-- | <http://llvm.org/doxygen/classllvm_1_1InlineAsm.html>+data InlineAsm++instance ChildOf Value InlineAsm++-- | <http://llvm.org/doxygen/classllvm_1_1Type.html>+data Type++-- | <http://llvm.org/doxygen/classllvm_1_1Metadata.html>+data Metadata++-- | <http://www.llvm.org/docs/doxygen/html/classllvm_1_1MetadataAsValue.html>+data MetadataAsVal++instance ChildOf Value MetadataAsVal++-- | <http://llvm.org/docs/doxygen/html/classllvm_1_1raw__ostream.html>+data RawOStream++-- | <http://llvm.org/docs/doxygen/html/classllvm_1_1raw__pwrite__stream.html>+data RawPWriteStream++instance ChildOf RawOStream RawPWriteStream
+ src/LLVM/Internal/FFI/RawOStream.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}+module LLVM.Internal.FFI.RawOStream where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C+import Control.Exception (bracket)++import LLVM.Internal.FFI.ByteRangeCallback+import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.PtrHierarchy++type RawPWriteStreamCallback = Ptr RawPWriteStream -> IO ()++foreign import ccall "wrapper" wrapRawPWriteStreamCallback ::+ RawPWriteStreamCallback -> IO (FunPtr RawPWriteStreamCallback)++foreign import ccall safe "LLVM_Hs_WithFileRawPWriteStream" withFileRawPWriteStream' ::+ CString -> LLVMBool -> LLVMBool -> Ptr (OwnerTransfered CString) -> FunPtr RawPWriteStreamCallback -> IO LLVMBool++withFileRawPWriteStream :: CString -> LLVMBool -> LLVMBool -> Ptr (OwnerTransfered CString) -> RawPWriteStreamCallback -> IO LLVMBool+withFileRawPWriteStream p ex bin err c =+ bracket (wrapRawPWriteStreamCallback c) freeHaskellFunPtr (withFileRawPWriteStream' p ex bin err)++foreign import ccall safe "LLVM_Hs_WithBufferRawPWriteStream" withBufferRawPWriteStream' ::+ FunPtr ByteRangeCallback -> FunPtr RawPWriteStreamCallback -> IO ()++withBufferRawPWriteStream :: ByteRangeCallback -> RawPWriteStreamCallback -> IO ()+withBufferRawPWriteStream oc c =+ bracket (wrapRawPWriteStreamCallback c) freeHaskellFunPtr $ \c ->+ bracket (wrapByteRangeCallback oc) freeHaskellFunPtr $ \oc ->+ withBufferRawPWriteStream' oc c
+ src/LLVM/Internal/FFI/RawOStreamC.cpp view
@@ -0,0 +1,36 @@+#define __STDC_LIMIT_MACROS+#include "llvm-c/Core.h"+#include "llvm/Support/FileSystem.h"+#include "llvm/Support/raw_ostream.h"++using namespace llvm;+using sys::fs::F_None;+using sys::fs::F_Excl;+using sys::fs::F_Text;++extern "C" {++LLVMBool+LLVM_Hs_WithFileRawPWriteStream(const char *filename, LLVMBool excl,+ LLVMBool text, char **error,+ void (&callback)(raw_pwrite_stream &ostream)) {+ std::error_code e;+ raw_fd_ostream os(filename, e,+ (excl ? F_Excl : F_None) | (text ? F_Text : F_None));+ if (e) {+ *error = strdup(e.message().c_str());+ return false;+ }+ callback(os);+ return true;+}++void LLVM_Hs_WithBufferRawPWriteStream(+ void (&outputCallback)(const char *start, size_t length),+ void (&streamCallback)(raw_pwrite_stream &ostream)) {+ SmallString<0> s;+ raw_svector_ostream os(s);+ streamCallback(os);+ outputCallback(os.str().data(), s.size());+}+}
+ src/LLVM/Internal/FFI/SMDiagnostic.h view
@@ -0,0 +1,15 @@+#ifndef __LLVM_INTERNAL_FFI__SMDIAGNOSTIC__+#define __LLVM_INTERNAL_FFI__SMDIAGNOSTIC__++#define LLVM_HS_FOR_EACH_DIAGNOSTIC_KIND(macro) \+ macro(Error) \+ macro(Warning) \+ macro(Note)++typedef enum {+#define ENUM_CASE(k) LLVMDiagnosticKind ## k,+LLVM_HS_FOR_EACH_DIAGNOSTIC_KIND(ENUM_CASE)+#undef ENUM_CASE+} LLVMDiagnosticKind;++#endif
+ src/LLVM/Internal/FFI/SMDiagnostic.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}+-- | FFI functions for handling the LLVM SMDiagnostic class+module LLVM.Internal.FFI.SMDiagnostic where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.LLVMCTypes++data SMDiagnostic++-- | allocate an SMDiagnostic object+foreign import ccall unsafe "LLVM_Hs_CreateSMDiagnostic" createSMDiagnostic ::+ IO (Ptr SMDiagnostic)++foreign import ccall unsafe "LLVM_Hs_DisposeSMDiagnostic" disposeSMDiagnostic ::+ Ptr SMDiagnostic -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetSMDiagnosticKind" getSMDiagnosticKind ::+ Ptr SMDiagnostic -> IO DiagnosticKind++foreign import ccall unsafe "LLVM_Hs_GetSMDiagnosticLineNo" getSMDiagnosticLineNo ::+ Ptr SMDiagnostic -> IO CInt ++foreign import ccall unsafe "LLVM_Hs_GetSMDiagnosticColumnNo" getSMDiagnosticColumnNo ::+ Ptr SMDiagnostic -> IO CInt ++foreign import ccall unsafe "LLVM_Hs_GetSMDiagnosticFilename" getSMDiagnosticFilename ::+ Ptr SMDiagnostic -> Ptr CUInt -> IO CString ++foreign import ccall unsafe "LLVM_Hs_GetSMDiagnosticMessage" getSMDiagnosticMessage ::+ Ptr SMDiagnostic -> Ptr CUInt -> IO CString ++foreign import ccall unsafe "LLVM_Hs_GetSMDiagnosticLineContents" getSMDiagnosticLineContents ::+ Ptr SMDiagnostic -> Ptr CUInt -> IO CString +
+ src/LLVM/Internal/FFI/SMDiagnosticC.cpp view
@@ -0,0 +1,42 @@+#define __STDC_LIMIT_MACROS+#include "llvm/Config/llvm-config.h"+#include "llvm/IR/LLVMContext.h"++#include "llvm/Support/SourceMgr.h"+#include "llvm-c/Core.h"++#include "LLVM/Internal/FFI/SMDiagnostic.h"++using namespace llvm;++extern "C" {++SMDiagnostic *LLVM_Hs_CreateSMDiagnostic() { return new SMDiagnostic(); }+void LLVM_Hs_DisposeSMDiagnostic(SMDiagnostic *p) { delete p; }++LLVMDiagnosticKind LLVM_Hs_GetSMDiagnosticKind(SMDiagnostic *p) {+ switch(p->getKind()) {+#define ENUM_CASE(k) case SourceMgr::DK_ ## k: return LLVMDiagnosticKind ## k;+ LLVM_HS_FOR_EACH_DIAGNOSTIC_KIND(ENUM_CASE)+#undef ENUM_CASE+ default: return LLVMDiagnosticKind(0);+ }+}++int LLVM_Hs_GetSMDiagnosticLineNo(SMDiagnostic *p) { return p->getLineNo(); }+int LLVM_Hs_GetSMDiagnosticColumnNo(SMDiagnostic *p) { return p->getColumnNo(); }++const char *LLVM_Hs_GetSMDiagnosticFilename(SMDiagnostic *p, unsigned *len) { + *len = p->getFilename().size();+ return p->getFilename().data();+}+const char *LLVM_Hs_GetSMDiagnosticMessage(SMDiagnostic *p, unsigned *len) {+ *len = p->getMessage().size();+ return p->getMessage().data();+}+const char *LLVM_Hs_GetSMDiagnosticLineContents(SMDiagnostic *p, unsigned *len) {+ *len = p->getLineContents().size();+ return p->getLineContents().data();+}++}
+ src/LLVM/Internal/FFI/Target.h view
@@ -0,0 +1,71 @@+#ifndef __LLVM_INTERNAL_FFI__TARGET__H__+#define __LLVM_INTERNAL_FFI__TARGET__H__++#define LLVM_HS_FOR_EACH_RELOC_MODEL(macro) \+ macro(Default, Default) \+ macro(Static, Static) \+ macro(PIC, PIC_) \+ macro(DynamicNoPic, DynamicNoPIC)++#define LLVM_HS_FOR_EACH_CODE_MODEL(macro) \+ macro(Default) \+ macro(JITDefault) \+ macro(Small) \+ macro(Kernel) \+ macro(Medium) \+ macro(Large)++#define LLVM_HS_FOR_EACH_CODE_GEN_OPT_LEVEL(macro) \+ macro(None) \+ macro(Less) \+ macro(Default) \+ macro(Aggressive)++#define LLVM_HS_FOR_EACH_CODE_GEN_FILE_TYPE(macro) \+ macro(Assembly) \+ macro(Object)++#define LLVM_HS_FOR_EACH_TARGET_OPTION_FLAG(macro) \+ macro(PrintMachineCode) \+ macro(LessPreciseFPMADOption) \+ macro(UnsafeFPMath) \+ macro(NoInfsFPMath) \+ macro(NoNaNsFPMath) \+ macro(HonorSignDependentRoundingFPMathOption) \+ macro(NoZerosInBSS) \+ macro(GuaranteedTailCallOpt) \+ macro(EnableFastISel) \+ macro(UseInitArray) \+ macro(DisableIntegratedAS) \+ macro(CompressDebugSections) \+ macro(TrapUnreachable)++typedef enum {+#define ENUM_CASE(n) LLVM_Hs_TargetOptionFlag_ ## n,+ LLVM_HS_FOR_EACH_TARGET_OPTION_FLAG(ENUM_CASE)+#undef ENUM_CASE+} LLVM_Hs_TargetOptionFlag;++#define LLVM_HS_FOR_EACH_FLOAT_ABI(macro) \+ macro(Default) \+ macro(Soft) \+ macro(Hard)++typedef enum {+#define ENUM_CASE(n) LLVM_Hs_FloatABI_ ## n,+ LLVM_HS_FOR_EACH_FLOAT_ABI(ENUM_CASE)+#undef ENUM_CASE+} LLVM_Hs_FloatABI;++#define LLVM_HS_FOR_EACH_FP_OP_FUSION_MODE(macro) \+ macro(Fast) \+ macro(Standard) \+ macro(Strict)++typedef enum {+#define ENUM_CASE(n) LLVM_Hs_FPOpFusionMode_ ## n,+ LLVM_HS_FOR_EACH_FP_OP_FUSION_MODE(ENUM_CASE)+#undef ENUM_CASE+} LLVM_Hs_FPOpFusionMode;++#endif
+ src/LLVM/Internal/FFI/Target.hpp view
@@ -0,0 +1,11 @@+#ifndef __LLVM_INTERNAL_FFI__TARGET__HPP__+#define __LLVM_INTERNAL_FFI__TARGET__HPP__++#include "llvm-c/TargetMachine.h"+#include "llvm/Target/TargetMachine.h"++namespace llvm {+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)+}++#endif
+ src/LLVM/Internal/FFI/Target.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE+ ForeignFunctionInterface,+ GeneralizedNewtypeDeriving+ #-}+module LLVM.Internal.FFI.Target where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.DataLayout+import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.MemoryBuffer+import LLVM.Internal.FFI.Module+import LLVM.Internal.FFI.PtrHierarchy++data Target++foreign import ccall unsafe "LLVM_Hs_InitializeNativeTarget" initializeNativeTarget ::+ IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_LookupTarget" lookupTarget ::+ CString -> CString -> Ptr (OwnerTransfered CString) -> Ptr (OwnerTransfered CString) -> IO (Ptr Target)++data TargetOptions++foreign import ccall unsafe "LLVM_Hs_CreateTargetOptions" createTargetOptions ::+ IO (Ptr TargetOptions)++foreign import ccall unsafe "LLVM_Hs_SetTargetOptionFlag" setTargetOptionFlag ::+ Ptr TargetOptions -> TargetOptionFlag -> LLVMBool -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetTargetOptionFlag" getTargetOptionsFlag ::+ Ptr TargetOptions -> TargetOptionFlag -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_SetStackAlignmentOverride" setStackAlignmentOverride ::+ Ptr TargetOptions -> CUInt -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetStackAlignmentOverride" getStackAlignmentOverride ::+ Ptr TargetOptions -> IO CUInt++foreign import ccall unsafe "LLVM_Hs_SetFloatABIType" setFloatABIType ::+ Ptr TargetOptions -> FloatABIType -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetFloatABIType" getFloatABIType ::+ Ptr TargetOptions -> IO FloatABIType++foreign import ccall unsafe "LLVM_Hs_SetAllowFPOpFusion" setAllowFPOpFusion ::+ Ptr TargetOptions -> FPOpFusionMode -> IO ()++foreign import ccall unsafe "LLVM_Hs_GetAllowFPOpFusion" getAllowFPOpFusion ::+ Ptr TargetOptions -> IO FPOpFusionMode++foreign import ccall unsafe "LLVM_Hs_DisposeTargetOptions" disposeTargetOptions ::+ Ptr TargetOptions -> IO ()++data TargetMachine++foreign import ccall unsafe "LLVMCreateTargetMachine" createTargetMachine ::+ Ptr Target+ -> CString+ -> CString+ -> CString+ -> Ptr TargetOptions+ -> RelocModel+ -> CodeModel+ -> CodeGenOptLevel+ -> IO (Ptr TargetMachine)++foreign import ccall unsafe "LLVMDisposeTargetMachine" disposeTargetMachine ::+ Ptr TargetMachine -> IO ()++foreign import ccall unsafe "LLVM_Hs_TargetMachineEmit" targetMachineEmit ::+ Ptr TargetMachine+ -> Ptr Module+ -> Ptr RawPWriteStream+ -> CodeGenFileType+ -> Ptr (OwnerTransfered CString)+ -> IO LLVMBool++foreign import ccall unsafe "LLVMTargetMachineEmitToFile" targetMachineEmitToFile ::+ Ptr TargetMachine+ -> Ptr Module+ -> CString+ -> CodeGenFileType+ -> Ptr (OwnerTransfered CString)+ -> IO LLVMBool++foreign import ccall unsafe "LLVMTargetMachineEmitToMemoryBuffer" targetMachineEmitToMemoryBuffer ::+ Ptr TargetMachine+ -> Ptr Module+ -> CodeGenFileType+ -> Ptr (OwnerTransfered CString)+ -> Ptr (Ptr MemoryBuffer)+ -> IO LLVMBool++data TargetLowering++-- foreign import ccall unsafe "LLVM_Hs_GetTargetLowering" getTargetLowering ::+-- Ptr TargetMachine -> IO (Ptr TargetLowering)++foreign import ccall unsafe "LLVMGetTargetMachineTriple" getTargetMachineTriple ::+ Ptr TargetMachine -> IO (OwnerTransfered CString)++foreign import ccall unsafe "LLVM_Hs_GetDefaultTargetTriple" getDefaultTargetTriple :: + IO (OwnerTransfered CString)++foreign import ccall unsafe "LLVM_Hs_GetProcessTargetTriple" getProcessTargetTriple :: + IO (OwnerTransfered CString)++foreign import ccall unsafe "LLVM_Hs_GetHostCPUName" getHostCPUName :: + Ptr CSize -> IO CString++foreign import ccall unsafe "LLVM_Hs_GetHostCPUFeatures" getHostCPUFeatures ::+ IO (OwnerTransfered CString)++foreign import ccall unsafe "LLVM_Hs_GetTargetMachineDataLayout" getTargetMachineDataLayout ::+ Ptr TargetMachine -> IO (OwnerTransfered CString)++data TargetLibraryInfo++foreign import ccall unsafe "LLVM_Hs_CreateTargetLibraryInfo" createTargetLibraryInfo ::+ CString -> IO (Ptr TargetLibraryInfo)++foreign import ccall unsafe "LLVM_Hs_GetLibFunc" getLibFunc ::+ Ptr TargetLibraryInfo -> CString -> Ptr LibFunc -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_LibFuncGetName" libFuncGetName ::+ Ptr TargetLibraryInfo -> LibFunc -> Ptr CSize -> IO CString++foreign import ccall unsafe "LLVM_Hs_LibFuncSetAvailableWithName" libFuncSetAvailableWithName ::+ Ptr TargetLibraryInfo -> LibFunc -> CString -> IO ()++foreign import ccall unsafe "LLVM_Hs_DisposeTargetLibraryInfo" disposeTargetLibraryInfo ::+ Ptr TargetLibraryInfo -> IO ()++foreign import ccall unsafe "LLVM_Hs_InitializeAllTargets" initializeAllTargets :: IO ()++foreign import ccall unsafe "LLVMCreateTargetDataLayout" createTargetDataLayout ::+ Ptr TargetMachine -> IO (Ptr DataLayout)
+ src/LLVM/Internal/FFI/TargetC.cpp view
@@ -0,0 +1,319 @@+#define __STDC_LIMIT_MACROS+#include "llvm-c/Target.h"+#include "LLVM/Internal/FFI/LibFunc.h"+#include "LLVM/Internal/FFI/Target.h"+#include "LLVM/Internal/FFI/Target.hpp"+#include "llvm-c/Core.h"+#include "llvm-c/TargetMachine.h"+#include "llvm/ADT/Triple.h"+#include "llvm/Analysis/TargetLibraryInfo.h"+#include "llvm/ExecutionEngine/Interpreter.h"+#include "llvm/IR/DataLayout.h"+#include "llvm/IR/LegacyPassManager.h"+#include "llvm/IR/Module.h"+#include "llvm/Support/FormattedStream.h"+#include "llvm/Support/Host.h"+#include "llvm/Support/TargetRegistry.h"+#include "llvm/Support/TargetSelect.h"+#include "llvm/Target/TargetMachine.h"++using namespace llvm;++namespace llvm {+// Taken from llvm/lib/Target/TargetMachineC.cpp+// These functions need to be marked as static to avoid undefined behavior+// due to multiple definitions+static LLVMTargetRef wrap(const Target *P) {+ return reinterpret_cast<LLVMTargetRef>(const_cast<Target *>(P));+}++static inline TargetLibraryInfoImpl *unwrap(LLVMTargetLibraryInfoRef P) {+ return reinterpret_cast<TargetLibraryInfoImpl*>(P);+}++static inline LLVMTargetLibraryInfoRef wrap(const TargetLibraryInfoImpl *P) {+ TargetLibraryInfoImpl *X = const_cast<TargetLibraryInfoImpl*>(P);+ return reinterpret_cast<LLVMTargetLibraryInfoRef>(X);+}++static FloatABI::ABIType unwrap(LLVM_Hs_FloatABI x) {+ switch (x) {+#define ENUM_CASE(x) \+ case LLVM_Hs_FloatABI_##x: \+ return FloatABI::x;+ LLVM_HS_FOR_EACH_FLOAT_ABI(ENUM_CASE)+#undef ENUM_CASE+ default:+ return FloatABI::ABIType(0);+ }+}++static LibFunc::Func unwrap(LLVMLibFunc x) {+ switch (x) {+#define ENUM_CASE(x) \+ case LLVMLibFunc__##x: \+ return LibFunc::x;+ LLVM_HS_FOR_EACH_LIB_FUNC(ENUM_CASE)+#undef ENUM_CASE+ default:+ return LibFunc::Func(0);+ }+}++static LLVMLibFunc wrap(LibFunc::Func x) {+ switch (x) {+#define ENUM_CASE(x) \+ case LibFunc::x: \+ return LLVMLibFunc__##x;+ LLVM_HS_FOR_EACH_LIB_FUNC(ENUM_CASE)+#undef ENUM_CASE+ default:+ return LLVMLibFunc(0);+ }+}++static LLVM_Hs_FloatABI wrap(FloatABI::ABIType x) {+ switch (x) {+#define ENUM_CASE(x) \+ case FloatABI::x: \+ return LLVM_Hs_FloatABI_##x;+ LLVM_HS_FOR_EACH_FLOAT_ABI(ENUM_CASE)+#undef ENUM_CASE+ default:+ return LLVM_Hs_FloatABI(0);+ }+}++static FPOpFusion::FPOpFusionMode unwrap(LLVM_Hs_FPOpFusionMode x) {+ switch (x) {+#define ENUM_CASE(x) \+ case LLVM_Hs_FPOpFusionMode_##x: \+ return FPOpFusion::x;+ LLVM_HS_FOR_EACH_FP_OP_FUSION_MODE(ENUM_CASE)+#undef ENUM_CASE+ default:+ return FPOpFusion::FPOpFusionMode(0);+ }+}++static LLVM_Hs_FPOpFusionMode wrap(FPOpFusion::FPOpFusionMode x) {+ switch (x) {+#define ENUM_CASE(x) \+ case FPOpFusion::x: \+ return LLVM_Hs_FPOpFusionMode_##x;+ LLVM_HS_FOR_EACH_FP_OP_FUSION_MODE(ENUM_CASE)+#undef ENUM_CASE+ default:+ return LLVM_Hs_FPOpFusionMode(0);+ }+}+}++extern "C" {++LLVMBool LLVM_Hs_InitializeNativeTarget() {+ return LLVMInitializeNativeTarget() || InitializeNativeTargetAsmPrinter() ||+ InitializeNativeTargetAsmParser();+}++LLVMTargetRef LLVM_Hs_LookupTarget(const char *arch, const char *ctriple,+ const char **tripleOut,+ const char **cerror) {+ std::string error;+ Triple triple(ctriple);+ if (const Target *result =+ TargetRegistry::lookupTarget(arch, triple, error)) {+ *tripleOut = strdup(triple.getTriple().c_str());+ return wrap(result);+ }+ *cerror = strdup(error.c_str());+ return 0;+}++TargetOptions *LLVM_Hs_CreateTargetOptions() {+ TargetOptions *to = new TargetOptions();+ return to;+}++void LLVM_Hs_SetTargetOptionFlag(TargetOptions *to,+ LLVM_Hs_TargetOptionFlag f,+ unsigned v) {+ switch (f) {+#define ENUM_CASE(op) \+ case LLVM_Hs_TargetOptionFlag_##op: \+ to->op = v ? 1 : 0; \+ break;+ LLVM_HS_FOR_EACH_TARGET_OPTION_FLAG(ENUM_CASE)+#undef ENUM_CASE+ }+}++unsigned LLVM_Hs_GetTargetOptionFlag(TargetOptions *to,+ LLVM_Hs_TargetOptionFlag f) {+ switch (f) {+#define ENUM_CASE(op) \+ case LLVM_Hs_TargetOptionFlag_##op: \+ return to->op;+ LLVM_HS_FOR_EACH_TARGET_OPTION_FLAG(ENUM_CASE)+#undef ENUM_CASE+ default:+ assert(false && "Unknown target option flag");+ return 0;+ }+}++void LLVM_Hs_SetStackAlignmentOverride(TargetOptions *to, unsigned v) {+ to->StackAlignmentOverride = v;+}++unsigned LLVM_Hs_GetStackAlignmentOverride(TargetOptions *to) {+ return to->StackAlignmentOverride;+}++void LLVM_Hs_SetFloatABIType(TargetOptions *to, LLVM_Hs_FloatABI v) {+ to->FloatABIType = unwrap(v);+}++LLVM_Hs_FloatABI LLVM_Hs_GetFloatABIType(TargetOptions *to) {+ return wrap(to->FloatABIType);+}++void LLVM_Hs_SetAllowFPOpFusion(TargetOptions *to,+ LLVM_Hs_FPOpFusionMode v) {+ to->AllowFPOpFusion = unwrap(v);+}++LLVM_Hs_FPOpFusionMode LLVM_Hs_GetAllowFPOpFusion(TargetOptions *to) {+ return wrap(to->AllowFPOpFusion);+}++void LLVM_Hs_DisposeTargetOptions(TargetOptions *t) { delete t; }++// const TargetLowering *LLVM_Hs_GetTargetLowering(LLVMTargetMachineRef t)+// {+// return unwrap(t)->getTargetLowering();+// }++char *LLVM_Hs_GetDefaultTargetTriple() {+ return strdup(sys::getDefaultTargetTriple().c_str());+}++char *LLVM_Hs_GetProcessTargetTriple() {+ return strdup(sys::getProcessTriple().c_str());+}++const char *LLVM_Hs_GetHostCPUName(size_t &len) {+ StringRef r = sys::getHostCPUName();+ len = r.size();+ return r.data();+}++char *LLVM_Hs_GetHostCPUFeatures() {+ StringMap<bool> featureMap;+ std::string features;+ if (sys::getHostCPUFeatures(featureMap)) {+ bool first = true;+ for (llvm::StringMap<bool>::const_iterator it = featureMap.begin();+ it != featureMap.end(); ++it) {+ if (!first) {+ features += ",";+ }+ first = false;+ features += (it->second ? "+" : "-") + it->first().str();+ }+ }+ return strdup(features.c_str());+}++char *LLVM_Hs_GetTargetMachineDataLayout(LLVMTargetMachineRef t) {+ return strdup(+ unwrap(t)->createDataLayout().getStringRepresentation().c_str());+}++LLVMTargetLibraryInfoRef+LLVM_Hs_CreateTargetLibraryInfo(const char *triple) {+ const TargetLibraryInfoImpl* p = new TargetLibraryInfoImpl(Triple(triple));+ return wrap(p);+}++LLVMBool LLVM_Hs_GetLibFunc(+ LLVMTargetLibraryInfoRef l,+ const char *funcName,+ LLVMLibFunc *f+) {+ LibFunc::Func func;+ LLVMBool result = unwrap(l)->getLibFunc(funcName, func);+ *f = wrap(func);+ return result;+}++const char *LLVM_Hs_LibFuncGetName(+ LLVMTargetLibraryInfoRef l,+ LLVMLibFunc f,+ size_t *nameSize+) {+ TargetLibraryInfo impl(*unwrap(l));+ StringRef s = impl.getName(unwrap(f));+ *nameSize = s.size();+ return s.data();+}++void LLVM_Hs_LibFuncSetAvailableWithName(+ LLVMTargetLibraryInfoRef l,+ LLVMLibFunc f,+ const char *name+) {+ unwrap(l)->setAvailableWithName(unwrap(f), name);+}++void LLVM_Hs_DisposeTargetLibraryInfo(LLVMTargetLibraryInfoRef l) {+ delete unwrap(l);+}++void LLVM_Hs_InitializeAllTargets() {+ InitializeAllTargetInfos();+ InitializeAllTargets();+ InitializeAllTargetMCs();+ InitializeAllAsmPrinters();+ // None of the other components are bound yet+}++// This is identical to LLVMTargetMachineEmit but LLVM doesn’t expose this function so we copy it here.+LLVMBool LLVM_Hs_TargetMachineEmit(+ LLVMTargetMachineRef T,+ LLVMModuleRef M,+ raw_pwrite_stream *OS,+ LLVMCodeGenFileType codegen,+ char **ErrorMessage+) {+ TargetMachine* TM = unwrap(T);+ Module* Mod = unwrap(M);++ legacy::PassManager pass;++ std::string error;++ Mod->setDataLayout(TM->createDataLayout());++ TargetMachine::CodeGenFileType ft;+ switch (codegen) {+ case LLVMAssemblyFile:+ ft = TargetMachine::CGFT_AssemblyFile;+ break;+ default:+ ft = TargetMachine::CGFT_ObjectFile;+ break;+ }+ if (TM->addPassesToEmitFile(pass, *OS, ft)) {+ error = "TargetMachine can't emit a file of this type";+ *ErrorMessage = strdup(error.c_str());+ return true;+ }++ pass.run(*Mod);++ OS->flush();+ return false;+}++}
+ src/LLVM/Internal/FFI/Threading.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}+module LLVM.Internal.FFI.Threading where++import LLVM.Prelude++import Foreign.C++import LLVM.Internal.FFI.LLVMCTypes++foreign import ccall unsafe "LLVMIsMultithreaded" isMultithreaded ::+ IO LLVMBool
+ src/LLVM/Internal/FFI/Transforms.hs view
@@ -0,0 +1,76 @@+-- | Code used with Template Haskell to build the FFI for transform passes.+module LLVM.Internal.FFI.Transforms where++import LLVM.Prelude++-- | does the constructor for this pass require a TargetMachine object+needsTargetMachine :: String -> Bool+needsTargetMachine "CodeGenPrepare" = True+needsTargetMachine _ = False++-- | Translate a Haskell name (used in the public Haskell interface, typically not abbreviated)+-- | for a pass into the (sometimes obscure, sometimes abbreviated) name used in the LLVM C interface.+-- | This translation includes, by choice of prefix, whether the C interface implementation is found in+-- | the LLVM distribution ("LLVM" prefix) or either not available or broken there and so implemented+-- | as part of this Haskell package ("LLVM_Hs_" prefix).+cName :: String -> String+cName n =+ let core = case n of+ "AddressSanitizer" -> "AddressSanitizerFunction"+ "AggressiveDeadCodeElimination" -> "AggressiveDCE"+ "AlwaysInline" -> "AlwaysInliner"+ "DeadInstructionElimination" -> "DeadInstElimination"+ "EarlyCommonSubexpressionElimination" -> "EarlyCSE"+ "FunctionAttributes" -> "FunctionAttrs"+ "GlobalDeadCodeElimination" -> "GlobalDCE"+ "InductionVariableSimplify" -> "IndVarSimplify"+ "InternalizeFunctions" -> "Internalize"+ "InterproceduralConstantPropagation" -> "IPConstantPropagation"+ "InterproceduralSparseConditionalConstantPropagation" -> "IPSCCP"+ "LoopClosedSingleStaticAssignment" -> "LCSSA"+ "LoopInvariantCodeMotion" -> "LICM"+ "LoopInstructionSimplify" -> "LoopInstSimplify"+ "MemcpyOptimization" -> "MemCpyOpt"+ "PruneExceptionHandling" -> "PruneEH"+ "ScalarReplacementOfAggregates" -> "SROA"+ "OldScalarReplacementOfAggregates" -> "ScalarReplAggregates"+ "SimplifyControlFlowGraph" -> "CFGSimplification"+ "SparseConditionalConstantPropagation" -> "SCCP"+ "SuperwordLevelParallelismVectorize" -> "SLPVectorize"+ h -> h+ patchImpls = [+ "AddressSanitizer",+ "AddressSanitizerModule",+ "BoundsChecking",+ "CodeGenPrepare",+ "GlobalValueNumbering",+ "InternalizeFunctions",+ "BasicBlockVectorize",+ "BlockPlacement",+ "BreakCriticalEdges",+ "DeadCodeElimination",+ "DeadInstructionElimination",+ "DemoteRegisterToMemory",+ "EdgeProfiler",+ "GCOVProfiler",+ "LoopClosedSingleStaticAssignment",+ "LoopInstructionSimplify",+ "LoopStrengthReduce",+ "LoopVectorize",+ "LowerAtomic",+ "LowerInvoke",+ "LowerSwitch",+ "MemorySanitizer",+ "MergeFunctions",+ "OptimalEdgeProfiler",+ "PathProfiler",+ "PartialInlining",+ "ScalarReplacementOfAggregates",+ "Sinking",+ "StripDeadDebugInfo",+ "StripDebugDeclare",+ "StripNonDebugSymbols",+ "ThreadSanitizer"+ ]+ in+ (if (n `elem` patchImpls) then "LLVM_Hs_" else "LLVM") ++ "Add" ++ core ++ "Pass"
+ src/LLVM/Internal/FFI/Type.h view
@@ -0,0 +1,23 @@+#ifndef __LLVM_INTERNAL_FFI__TYPE__H__+#define __LLVM_INTERNAL_FFI__TYPE__H__++#define LLVM_HS_FOR_EACH_TYPE_KIND(macro) \+ macro(Void) \+ macro(Half) \+ macro(Float) \+ macro(Double) \+ macro(X86_FP80) \+ macro(FP128) \+ macro(PPC_FP128) \+ macro(Label) \+ macro(Integer) \+ macro(Function) \+ macro(Struct) \+ macro(Array) \+ macro(Pointer) \+ macro(Vector) \+ macro(Metadata) \+ macro(X86_MMX) \+ macro(Token)++#endif
+ src/LLVM/Internal/FFI/Type.hs view
@@ -0,0 +1,152 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}+-- | Functions for handling the LLVM types+module LLVM.Internal.FFI.Type where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.Context+import LLVM.Internal.FFI.PtrHierarchy++-- | <http://llvm.org/doxygen/group__LLVMCCoreType.html#ga112756467f0988613faa6043d674d843>+foreign import ccall unsafe "LLVMGetTypeKind" getTypeKind ::+ Ptr Type -> IO TypeKind++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeInt.html#gadfb8ba2f605f0860a4bf2e3c480ab6a2>+foreign import ccall unsafe "LLVMGetIntTypeWidth" getIntTypeWidth ::+ Ptr Type -> IO (CUInt)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeFunction.html#ga2970f0f4d9ee8a0f811f762fb2fa7f82>+foreign import ccall unsafe "LLVMIsFunctionVarArg" isFunctionVarArg ::+ Ptr Type -> IO LLVMBool++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeFunction.html#gacfa4594cbff421733add602a413cae9f>+foreign import ccall unsafe "LLVMGetReturnType" getReturnType ::+ Ptr Type -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeFunction.html#ga44fa41d22ed1f589b8202272f54aad77>+foreign import ccall unsafe "LLVMCountParamTypes" countParamTypes ::+ Ptr Type -> IO CUInt++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeFunction.html#ga83dd3a49a0f3f017f4233fc0d667bda2>+foreign import ccall unsafe "LLVMGetParamTypes" getParamTypes ::+ Ptr Type -> Ptr (Ptr Type) -> IO ()++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeSequential.html#ga0b03e26a2d254530a9b5c279cdf52257>+foreign import ccall unsafe "LLVMGetElementType" getElementType ::+ Ptr Type -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeInt.html#ga2e5db8cbc30daa156083f2c42989138d>+foreign import ccall unsafe "LLVMIntTypeInContext" intTypeInContext ::+ Ptr Context -> CUInt -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeFunction.html#ga8b0c32e7322e5c6c1bf7eb95b0961707>+foreign import ccall unsafe "LLVMFunctionType" functionType' ::+ Ptr Type -> Ptr (Ptr Type) -> CUInt -> LLVMBool -> IO (Ptr Type)++functionType :: Ptr Type -> (CUInt, Ptr (Ptr Type)) -> LLVMBool -> IO (Ptr Type)+functionType rt (n, ats) va = functionType' rt ats n va++newtype AddrSpace = AddrSpace CUInt+-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeSequential.html#ga299fe6147083678d0494b1b875f542fae>+foreign import ccall unsafe "LLVMPointerType" pointerType ::+ Ptr Type -> AddrSpace -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeSequential.html#ga124b162b69b5def41dde2fda3668cbd9>+foreign import ccall unsafe "LLVMGetPointerAddressSpace" getPointerAddressSpace ::+ Ptr Type -> IO AddrSpace++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeSequential.html#ga5ec731adf74fb40bc3b401956d0c6ff2>+foreign import ccall unsafe "LLVMVectorType" vectorType ::+ Ptr Type -> CUInt -> IO (Ptr Type)++-- | what <http://llvm.org/doxygen/group__LLVMCCoreTypeSequential.html#gabd1666e080f693e1af0b4018005cd927>+-- | would be if it supported 64-bit array sizes, as the C++ type does.+foreign import ccall unsafe "LLVM_Hs_ArrayType" arrayType ::+ Ptr Type -> Word64 -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeStruct.html#gaff2af74740a22f7d18701f0d8c3e5a6f>+foreign import ccall unsafe "LLVMStructTypeInContext" structTypeInContext' ::+ Ptr Context -> Ptr (Ptr Type) -> CUInt -> LLVMBool -> IO (Ptr Type)++structTypeInContext :: Ptr Context -> (CUInt, Ptr (Ptr Type)) -> LLVMBool -> IO (Ptr Type)+structTypeInContext ctx (n, ts) p = structTypeInContext' ctx ts n p++foreign import ccall unsafe "LLVM_Hs_StructCreateNamed" structCreateNamed ::+ Ptr Context -> CString -> IO (Ptr Type)++foreign import ccall unsafe "LLVMGetStructName" getStructName ::+ Ptr Type -> IO CString++foreign import ccall unsafe "LLVM_Hs_StructIsLiteral" structIsLiteral ::+ Ptr Type -> IO LLVMBool++foreign import ccall unsafe "LLVM_Hs_StructIsOpaque" structIsOpaque ::+ Ptr Type -> IO LLVMBool++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeStruct.html#ga3e940e660375ae0cbdde81c0d8ec91e3>+foreign import ccall unsafe "LLVMIsPackedStruct" isPackedStruct ::+ Ptr Type -> IO LLVMBool++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeStruct.html#gaf32e6d6bcec38b786efbef689b0dddf7>+foreign import ccall unsafe "LLVMCountStructElementTypes" countStructElementTypes ::+ Ptr Type -> IO CUInt++foreign import ccall unsafe "LLVMGetStructElementTypes" getStructElementTypes ::+ Ptr Type -> Ptr (Ptr Type) -> IO ()++foreign import ccall unsafe "LLVMStructSetBody" structSetBody' ::+ Ptr Type -> Ptr (Ptr Type) -> CUInt -> LLVMBool -> IO ()++structSetBody :: Ptr Type -> (CUInt, Ptr (Ptr Type)) -> LLVMBool -> IO ()+structSetBody s (n,ts) p = structSetBody' s ts n p++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeSequential.html#gafb88a5ebd2a8062e105854910dc7ca17>+foreign import ccall unsafe "LLVMGetVectorSize" getVectorSize ::+ Ptr Type -> IO CUInt++-- | what <http://llvm.org/doxygen/group__LLVMCCoreTypeSequential.html#ga02dc08041a12265cb700ee469497df63>+-- | would be if it supported 64 bit lengths+foreign import ccall unsafe "LLVM_Hs_GetArrayLength" getArrayLength ::+ Ptr Type -> IO Word64++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeOther.html#ga1c78ca6d7bf279330b9195fa52f23828>+foreign import ccall unsafe "LLVMVoidTypeInContext" voidTypeInContext ::+ Ptr Context -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeFloat.html#ga3a5332a1d075602bccad7576d1a8e36f>+foreign import ccall unsafe "LLVMHalfTypeInContext" halfTypeInContext ::+ Ptr Context -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeFloat.html#ga529c83a8a5461e5beac19eb867216e3c>+foreign import ccall unsafe "LLVMFloatTypeInContext" floatTypeInContext ::+ Ptr Context -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeFloat.html#ga200527010747eab31b73d3e3f6d94935>+foreign import ccall unsafe "LLVMDoubleTypeInContext" doubleTypeInContext ::+ Ptr Context -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeFloat.html#ga24f77b84b625ed3dd516b52480606093>+foreign import ccall unsafe "LLVMX86FP80TypeInContext" x86FP80TypeInContext ::+ Ptr Context -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeFloat.html#ga1c02fb08f9ae12a719ed42099d42ccd8>+foreign import ccall unsafe "LLVMFP128TypeInContext" fP128TypeInContext ::+ Ptr Context -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreTypeFloat.html#gac2491184fc3d8631c7b264c067f2f761>+foreign import ccall unsafe "LLVMPPCFP128TypeInContext" ppcFP128TypeInContext ::+ Ptr Context -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/classllvm_1_1Type.html#a28fdf240b8220065bc60d6d1b1a2f174>+foreign import ccall unsafe "LLVM_Hs_MetadataTypeInContext" metadataTypeInContext ::+ Ptr Context -> IO (Ptr Type)++-- | <http://llvm.org/docs/doxygen/html/Core_8cpp.html#a5d3702e198e2373db7e31bb18879efc3>+foreign import ccall unsafe "LLVM_Hs_TokenTypeInContext" tokenTypeInContext ::+ Ptr Context -> IO (Ptr Type)
+ src/LLVM/Internal/FFI/TypeC.cpp view
@@ -0,0 +1,42 @@+#define __STDC_LIMIT_MACROS+#include "llvm-c/Core.h"+#include "llvm/IR/DerivedTypes.h"+#include "llvm/IR/LLVMContext.h"+#include "llvm/IR/Type.h"++using namespace llvm;++extern "C" {++LLVMTypeRef LLVM_Hs_StructCreateNamed(LLVMContextRef C, const char *Name) {+ if (Name) {+ return wrap(StructType::create(*unwrap(C), Name));+ } else {+ return wrap(StructType::create(*unwrap(C)));+ }+}++LLVMBool LLVM_Hs_StructIsLiteral(LLVMTypeRef t) {+ return unwrap<StructType>(t)->isLiteral();+}++LLVMBool LLVM_Hs_StructIsOpaque(LLVMTypeRef t) {+ return unwrap<StructType>(t)->isOpaque();+}++LLVMTypeRef LLVM_Hs_ArrayType(LLVMTypeRef ElementType, uint64_t ElementCount) {+ return wrap(ArrayType::get(unwrap(ElementType), ElementCount));+}++uint64_t LLVM_Hs_GetArrayLength(LLVMTypeRef ArrayTy) {+ return unwrap<ArrayType>(ArrayTy)->getNumElements();+}++LLVMTypeRef LLVM_Hs_MetadataTypeInContext(LLVMContextRef C) {+ return wrap(Type::getMetadataTy(*unwrap(C)));+}++LLVMTypeRef LLVM_Hs_TokenTypeInContext(LLVMContextRef C) {+ return wrap(Type::getTokenTy(*unwrap(C)));+}+}
+ src/LLVM/Internal/FFI/User.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE+ ForeignFunctionInterface,+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+-- | FFI functions for handling the LLVM User class+module LLVM.Internal.FFI.User where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.PtrHierarchy++-- | a blind type to correspond to llvm::Use+data Use++-- | test if a 'Value' is a 'User'+foreign import ccall unsafe "LLVMIsAUser" isAUser ::+ Ptr Value -> IO (Ptr User)++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueUses.html#ga66a226d3d06ffada5c929656f4d97d35>+foreign import ccall unsafe "LLVMGetFirstUse" getFirstUse ::+ Ptr User -> IO (Ptr Use)++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueUses.html#ga6ea72661bcca2b77bea57173317ec942>+foreign import ccall unsafe "LLVMGetNextUse" getNextUse ::+ Ptr Use -> IO (Ptr Use)++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueUser.html#ga2ad633a6afc7906f1afe329f244240f6>+foreign import ccall unsafe "LLVMGetNumOperands" getNumOperands ::+ Ptr User -> IO CUInt++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueUser.html#ga799d58a361054323cb457945071cbfdb>+foreign import ccall unsafe "LLVMGetOperand" getOperand ::+ Ptr User -> CUInt -> IO (Ptr Value)+
+ src/LLVM/Internal/FFI/Value.h view
@@ -0,0 +1,32 @@+#ifndef __LLVM_INTERNAL_FFI__VALUE__H__+#define __LLVM_INTERNAL_FFI__VALUE__H__++#define LLVM_HS_FOR_EACH_VALUE_SUBCLASS(macro) \+ macro(Argument) \+ macro(BasicBlock) \+ macro(Function) \+ macro(GlobalAlias) \+ macro(GlobalVariable) \+ macro(UndefValue) \+ macro(BlockAddress) \+ macro(ConstantExpr) \+ macro(ConstantAggregateZero) \+ macro(ConstantDataArray) \+ macro(ConstantDataVector) \+ macro(ConstantInt) \+ macro(ConstantFP) \+ macro(ConstantArray) \+ macro(ConstantStruct) \+ macro(ConstantTokenNone) \+ macro(ConstantVector) \+ macro(ConstantPointerNull) \+ macro(InlineAsm) \+ macro(Instruction)++typedef enum {+#define ENUM_CASE(class) LLVM ## class ## SubclassId,+LLVM_HS_FOR_EACH_VALUE_SUBCLASS(ENUM_CASE)+#undef ENUM_CASE+} LLVMValueSubclassId;++#endif
+ src/LLVM/Internal/FFI/Value.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE+ ForeignFunctionInterface,+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+-- | FFI functions for handling the LLVM Value class+module LLVM.Internal.FFI.Value where++import LLVM.Prelude++import Foreign.Ptr+import Foreign.C++import LLVM.Internal.FFI.LLVMCTypes+import LLVM.Internal.FFI.PtrHierarchy++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueGeneral.html#ga12179f46b79de8436852a4189d4451e0>+foreign import ccall unsafe "LLVMTypeOf" typeOf ::+ Ptr Value -> IO (Ptr Type)++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueGeneral.html#ga70948786725c43968d15225dd584e5a9>+foreign import ccall unsafe "LLVMGetValueName" getValueName ::+ Ptr Value -> IO CString++-- | <http://llvm.org/doxygen/group__LLVMCCoreValueGeneral.html#gac1f61f74d83d218d4943c018e8fd8d13>+foreign import ccall unsafe "LLVMSetValueName" setValueName ::+ Ptr Value -> CString -> IO ()++-- | This function exposes the ID returned by llvm::Value::getValueID()+-- | <http://llvm.org/doxygen/classllvm_1_1Value.html#a2983b7b4998ef5b9f51b18c01588af3c>. +foreign import ccall unsafe "LLVM_Hs_GetValueSubclassId" getValueSubclassId ::+ Ptr Value -> IO ValueSubclassId++foreign import ccall unsafe "LLVMReplaceAllUsesWith" replaceAllUsesWith ::+ Ptr Value -> Ptr Value -> IO ()++foreign import ccall unsafe "LLVM_Hs_CreateArgument" createArgument ::+ Ptr Type -> CString -> IO (Ptr Value)++foreign import ccall unsafe "LLVMDumpValue" dumpValue ::+ Ptr Value -> IO ()
+ src/LLVM/Internal/FFI/ValueC.cpp view
@@ -0,0 +1,30 @@+#define __STDC_LIMIT_MACROS+#include "llvm-c/Core.h"+#include "llvm/IR/Type.h"+#include "llvm/IR/DerivedTypes.h"+#include "llvm/IR/Value.h"+#include "llvm/IR/Argument.h"+#include "LLVM/Internal/FFI/Value.h"++using namespace llvm;++extern "C" {++LLVMValueSubclassId LLVM_Hs_GetValueSubclassId(LLVMValueRef v) {+ switch(unwrap(v)->getValueID()) {+#define VALUE_SUBCLASS_ID_CASE(class) case Value::class ## Val: return LLVM ## class ## SubclassId;+LLVM_HS_FOR_EACH_VALUE_SUBCLASS(VALUE_SUBCLASS_ID_CASE)+#undef VALUE_SUBCLASS_ID_CASE+ default: break;+ }+ return LLVMValueSubclassId(0);+}++LLVMValueRef LLVM_Hs_CreateArgument(+ LLVMTypeRef t,+ const char *name+) {+ return wrap(new Argument(unwrap(t), name));+}++}
+ src/LLVM/Internal/FastMathFlags.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE + MultiParamTypeClasses+ #-}+module LLVM.Internal.FastMathFlags where++import LLVM.Prelude++import Control.Monad.Trans+import Control.Monad.AnyCont+import Control.Monad.State+import Control.Exception++import Data.Bits++import qualified LLVM.Internal.FFI.Builder as FFI+import qualified LLVM.Internal.FFI.LLVMCTypes as FFI++import LLVM.Internal.Coding+import LLVM.Internal.EncodeAST++import qualified LLVM.AST as A++instance EncodeM IO A.FastMathFlags FFI.FastMathFlags where+ encodeM A.NoFastMathFlags = return 0+ encodeM A.UnsafeAlgebra = return FFI.fastMathFlagsUnsafeAlgebra+ encodeM f = return $ foldr1 (.|.) [ + if a f then b else 0+ | (a,b) <- [+ (A.noNaNs, FFI.fastMathFlagsNoNaNs),+ (A.noInfs, FFI.fastMathFlagsNoInfs),+ (A.noSignedZeros, FFI.fastMathFlagsNoSignedZeros),+ (A.allowReciprocal, FFI.fastMathFlagsAllowReciprocal)+ ] + ]++instance EncodeM EncodeAST A.FastMathFlags () where+ encodeM f = do + f <- liftIO $ encodeM f+ builder <- gets encodeStateBuilder+ anyContToM $ bracket (FFI.setFastMathFlags builder f) (\() -> FFI.setFastMathFlags builder 0)++instance Monad m => DecodeM m A.FastMathFlags FFI.FastMathFlags where+ decodeM 0 = return A.NoFastMathFlags+ decodeM f | FFI.fastMathFlagsUnsafeAlgebra .&. f /= 0 = return A.UnsafeAlgebra+ decodeM f = return A.FastMathFlags {+ A.noNaNs = FFI.fastMathFlagsNoNaNs .&. f /= 0,+ A.noInfs = FFI.fastMathFlagsNoInfs .&. f /= 0,+ A.noSignedZeros = FFI.fastMathFlagsNoSignedZeros .&. f /= 0,+ A.allowReciprocal = FFI.fastMathFlagsAllowReciprocal .&. f /= 0+ }+
+ src/LLVM/Internal/FloatingPointPredicate.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE+ MultiParamTypeClasses,+ TemplateHaskell+ #-}+module LLVM.Internal.FloatingPointPredicate where++import LLVM.Internal.Coding++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import qualified LLVM.AST.FloatingPointPredicate as A.FPPred++genCodingInstance [t| A.FPPred.FloatingPointPredicate |] ''FFI.FCmpPredicate [+ (FFI.fCmpPredFalse, A.FPPred.False),+ (FFI.fCmpPredOEQ, A.FPPred.OEQ),+ (FFI.fCmpPredOGT, A.FPPred.OGT),+ (FFI.fCmpPredOGE, A.FPPred.OGE),+ (FFI.fCmpPredOLT, A.FPPred.OLT),+ (FFI.fCmpPredOLE, A.FPPred.OLE),+ (FFI.fCmpPredONE, A.FPPred.ONE),+ (FFI.fCmpPredORD, A.FPPred.ORD),+ (FFI.fCmpPredUNO, A.FPPred.UNO),+ (FFI.fCmpPredUEQ, A.FPPred.UEQ),+ (FFI.fCmpPredUGT, A.FPPred.UGT),+ (FFI.fCmpPredUGE, A.FPPred.UGE),+ (FFI.fCmpPredULT, A.FPPred.ULT),+ (FFI.fCmpPredULE, A.FPPred.ULE),+ (FFI.fCmpPredUNE, A.FPPred.UNE),+ (FFI.fcmpPredTrue, A.FPPred.True)+ ]
+ src/LLVM/Internal/Function.hs view
@@ -0,0 +1,70 @@+module LLVM.Internal.Function where++import LLVM.Prelude++import Control.Monad.Trans+import Control.Monad.AnyCont++import Foreign.C (CUInt)+import Foreign.Ptr ++import Data.Map (Map)+import qualified Data.Map as Map++import qualified LLVM.Internal.FFI.Function as FFI+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI++import LLVM.Internal.DecodeAST+import LLVM.Internal.EncodeAST+import LLVM.Internal.Value+import LLVM.Internal.Coding+import LLVM.Internal.Constant ()+import LLVM.Internal.Attribute++import qualified LLVM.AST as A+import qualified LLVM.AST.Constant as A+import qualified LLVM.AST.ParameterAttribute as A.PA ++getMixedAttributeSet :: Ptr FFI.Function -> DecodeAST MixedAttributeSet+getMixedAttributeSet = decodeM <=< liftIO . FFI.getMixedAttributeSet++setFunctionAttributes :: Ptr FFI.Function -> MixedAttributeSet -> EncodeAST ()+setFunctionAttributes f = (liftIO . FFI.setMixedAttributeSet f) <=< encodeM++getParameters :: Ptr FFI.Function -> Map CUInt [A.PA.ParameterAttribute] -> DecodeAST [A.Parameter]+getParameters f attrs = scopeAnyCont $ do+ n <- liftIO (FFI.countParams f)+ ps <- allocaArray n+ liftIO $ FFI.getParams f ps+ params <- peekArray n ps+ forM (zip params [0..]) $ \(param, i) -> + return A.Parameter + `ap` typeOf param+ `ap` getLocalName param+ `ap` (return $ Map.findWithDefault [] i attrs)+ +getGC :: Ptr FFI.Function -> DecodeAST (Maybe String)+getGC f = scopeAnyCont $ decodeM =<< liftIO (FFI.getGC f)++setGC :: Ptr FFI.Function -> Maybe String -> EncodeAST ()+setGC f gc = scopeAnyCont $ liftIO . FFI.setGC f =<< encodeM gc ++getPrefixData :: Ptr FFI.Function -> DecodeAST (Maybe A.Constant)+getPrefixData f = do+ has <- decodeM =<< (liftIO $ FFI.hasPrefixData f)+ if has+ then decodeM =<< (liftIO $ FFI.getPrefixData f)+ else return Nothing++setPrefixData :: Ptr FFI.Function -> Maybe A.Constant -> EncodeAST ()+setPrefixData f = maybe (return ()) (liftIO . FFI.setPrefixData f <=< encodeM)++getPersonalityFn :: Ptr FFI.Function -> DecodeAST (Maybe A.Constant)+getPersonalityFn f = do+ has <- decodeM =<< liftIO (FFI.hasPersonalityFn f)+ if has+ then decodeM =<< liftIO (FFI.getPersonalityFn f)+ else pure Nothing++setPersonalityFn :: Ptr FFI.Function -> Maybe A.Constant -> EncodeAST ()+setPersonalityFn f personality = (liftIO . FFI.setPersonalityFn f =<< encodeM personality)
+ src/LLVM/Internal/Global.hs view
@@ -0,0 +1,146 @@+{-# LANGUAGE+ TemplateHaskell,+ MultiParamTypeClasses+ #-}+module LLVM.Internal.Global where++import LLVM.Prelude++import Control.Monad.State+import Control.Monad.AnyCont+import Foreign.Ptr+import qualified Data.Map as Map++import qualified LLVM.Internal.FFI.PtrHierarchy as FFI+import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import qualified LLVM.Internal.FFI.GlobalValue as FFI++import LLVM.Internal.Coding+import LLVM.Internal.DecodeAST+import LLVM.Internal.EncodeAST++import qualified LLVM.AST.Linkage as A.L+import qualified LLVM.AST.Visibility as A.V+import qualified LLVM.AST.COMDAT as A.COMDAT+import qualified LLVM.AST.DLL as A.DLL+import qualified LLVM.AST.ThreadLocalStorage as A.TLS+import qualified LLVM.AST.Global as A.G++genCodingInstance [t| A.L.Linkage |] ''FFI.Linkage [+ (FFI.linkageExternal, A.L.External),+ (FFI.linkageAvailableExternally, A.L.AvailableExternally),+ (FFI.linkageLinkOnceAny, A.L.LinkOnce),+ (FFI.linkageLinkOnceODR, A.L.LinkOnceODR),+ (FFI.linkageWeakAny, A.L.Weak),+ (FFI.linkageWeakODR, A.L.WeakODR),+ (FFI.linkageAppending, A.L.Appending),+ (FFI.linkageInternal, A.L.Internal),+ (FFI.linkagePrivate, A.L.Private),+ (FFI.linkageExternalWeak, A.L.ExternWeak),+ (FFI.linkageCommon, A.L.Common)+ ]++getLinkage :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST A.L.Linkage+getLinkage g = liftIO $ decodeM =<< FFI.getLinkage (FFI.upCast g)++setLinkage :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> A.L.Linkage -> EncodeAST ()+setLinkage g l = liftIO . FFI.setLinkage (FFI.upCast g) =<< encodeM l+ +genCodingInstance [t| A.V.Visibility |] ''FFI.Visibility [+ (FFI.visibilityDefault, A.V.Default),+ (FFI.visibilityHidden, A.V.Hidden),+ (FFI.visibilityProtected, A.V.Protected)+ ]++getVisibility :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST A.V.Visibility+getVisibility g = liftIO $ decodeM =<< FFI.getVisibility (FFI.upCast g)++setVisibility :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> A.V.Visibility -> EncodeAST ()+setVisibility g v = liftIO . FFI.setVisibility (FFI.upCast g) =<< encodeM v++genCodingInstance [t| Maybe A.DLL.StorageClass |] ''FFI.DLLStorageClass [+ (FFI.dllStorageClassDefault, Nothing),+ (FFI.dllStorageClassDLLImport, Just A.DLL.Import),+ (FFI.dllStorageClassDLLExport, Just A.DLL.Export)+ ]++getDLLStorageClass :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST (Maybe A.DLL.StorageClass)+getDLLStorageClass g = liftIO $ decodeM =<< FFI.getDLLStorageClass (FFI.upCast g)++setDLLStorageClass :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> Maybe A.DLL.StorageClass -> EncodeAST ()+setDLLStorageClass g sc = liftIO . FFI.setDLLStorageClass (FFI.upCast g) =<< encodeM sc++getSection :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST (Maybe String)+getSection g = do+ sectionLengthPtr <- alloca+ sectionNamePtr <- liftIO $ FFI.getSection (FFI.upCast g) sectionLengthPtr+ if sectionNamePtr == nullPtr then+ return Nothing+ else+ do sectionLength <- peek sectionLengthPtr+ sectionName <- decodeM (sectionNamePtr, sectionLength)+ return (Just sectionName)++setSection :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> Maybe String -> EncodeAST ()+setSection g s = scopeAnyCont $ do+ s <- encodeM (maybe "" id s)+ liftIO $ FFI.setSection (FFI.upCast g) s++genCodingInstance [t| A.COMDAT.SelectionKind |] ''FFI.COMDATSelectionKind [+ (FFI.comdatSelectionKindAny, A.COMDAT.Any),+ (FFI.comdatSelectionKindExactMatch, A.COMDAT.ExactMatch),+ (FFI.comdatSelectionKindLargest, A.COMDAT.Largest),+ (FFI.comdatSelectionKindNoDuplicates, A.COMDAT.NoDuplicates),+ (FFI.comdatSelectionKindSameSize, A.COMDAT.SameSize)+ ]++instance DecodeM DecodeAST (String, A.COMDAT.SelectionKind) (Ptr FFI.COMDAT) where+ decodeM c = return (,)+ `ap` (decodeM $ FFI.getCOMDATName c)+ `ap` (decodeM =<< liftIO (FFI.getCOMDATSelectionKind c))++getCOMDATName :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST (Maybe String)+getCOMDATName g = do+ c <- liftIO $ FFI.getCOMDAT (FFI.upCast g)+ if c == nullPtr+ then return Nothing+ else do+ cds <- gets comdats+ liftM Just $ case Map.lookup c cds of+ Just (name, _) -> return name+ Nothing -> do+ cd@(name, _) <- decodeM c+ modify $ \s -> s { comdats = Map.insert c cd cds }+ return name++setCOMDAT :: FFI.DescendentOf FFI.GlobalObject v => Ptr v -> Maybe String -> EncodeAST ()+setCOMDAT _ Nothing = return ()+setCOMDAT g (Just name) = do+ cd <- referCOMDAT name+ liftIO $ FFI.setCOMDAT (FFI.upCast g) cd++setAlignment :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> Word32 -> EncodeAST ()+setAlignment g i = liftIO $ FFI.setAlignment (FFI.upCast g) (fromIntegral i)++getAlignment :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST Word32+getAlignment g = liftIO $ fromIntegral <$> FFI.getAlignment (FFI.upCast g)++genCodingInstance [t| Maybe A.TLS.Model |] ''FFI.ThreadLocalMode [+ (FFI.threadLocalModeNotThreadLocal, Nothing),+ (FFI.threadLocalModeGeneralDynamicTLSModel, Just A.TLS.GeneralDynamic),+ (FFI.threadLocalModeLocalDynamicTLSModel, Just A.TLS.LocalDynamic),+ (FFI.threadLocalModeInitialExecTLSModel, Just A.TLS.InitialExec),+ (FFI.threadLocalModeLocalExecTLSModel, Just A.TLS.LocalExec)+ ]++getThreadLocalMode :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST (Maybe A.TLS.Model)+getThreadLocalMode g = liftIO $ decodeM =<< FFI.getThreadLocalMode (FFI.upCast g)++setThreadLocalMode :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> Maybe A.TLS.Model -> EncodeAST ()+setThreadLocalMode g m = liftIO . FFI.setThreadLocalMode (FFI.upCast g) =<< encodeM m++genCodingInstance [t| Maybe A.G.UnnamedAddr |] ''FFI.UnnamedAddr [+ (FFI.unnamedAddrNone, Nothing),+ (FFI.unnamedAddrLocal, Just A.G.LocalAddr),+ (FFI.unnamedAddrGlobal, Just A.G.GlobalAddr)+ ]
+ src/LLVM/Internal/Inject.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE MultiParamTypeClasses #-}+module LLVM.Internal.Inject where++import LLVM.Prelude++class Inject a b where+ inject :: a -> b++instance Inject a a where+ inject = id+
+ src/LLVM/Internal/InlineAssembly.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE+ TemplateHaskell,+ MultiParamTypeClasses+ #-}+module LLVM.Internal.InlineAssembly where+ +import LLVM.Prelude++import Control.Monad.IO.Class++import Foreign.C+import Foreign.Ptr++import qualified LLVM.Internal.FFI.InlineAssembly as FFI+import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import qualified LLVM.Internal.FFI.Module as FFI+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI++import qualified LLVM.AST as A (Definition(..))+import qualified LLVM.AST.InlineAssembly as A+import qualified LLVM.AST.Type as A++import LLVM.Internal.Coding +import LLVM.Internal.EncodeAST+import LLVM.Internal.DecodeAST+import LLVM.Internal.Value++genCodingInstance [t| A.Dialect |] ''FFI.AsmDialect [+ (FFI.asmDialectATT, A.ATTDialect),+ (FFI.asmDialectIntel, A.IntelDialect)+ ]++instance EncodeM EncodeAST A.InlineAssembly (Ptr FFI.InlineAsm) where+ encodeM (A.InlineAssembly {+ A.type' = t,+ A.assembly = assembly,+ A.constraints = constraints,+ A.hasSideEffects = hasSideEffects,+ A.alignStack = alignStack,+ A.dialect = dialect+ }) = do+ t <- encodeM t+ assembly <- encodeM assembly+ constraints <- encodeM constraints+ hasSideEffects <- encodeM hasSideEffects+ alignStack <- encodeM alignStack+ dialect <- encodeM dialect+ liftIO $ FFI.createInlineAsm t assembly constraints hasSideEffects alignStack dialect++instance DecodeM DecodeAST A.InlineAssembly (Ptr FFI.InlineAsm) where+ decodeM p = do+ return A.InlineAssembly+ `ap` (liftM (\(A.PointerType f _) -> f) (typeOf p))+ `ap` (decodeM =<< liftIO (FFI.getInlineAsmAssemblyString p))+ `ap` (decodeM =<< liftIO (FFI.getInlineAsmConstraintString p))+ `ap` (decodeM =<< liftIO (FFI.inlineAsmHasSideEffects p))+ `ap` (decodeM =<< liftIO (FFI.inlineAsmIsAlignStack p))+ `ap` (decodeM =<< liftIO (FFI.getInlineAsmDialect p))++instance DecodeM DecodeAST [A.Definition] (FFI.ModuleAsm CString) where+ decodeM (FFI.ModuleAsm s) = do+ s <- decodeM s+ let takeModIA "" = []+ takeModIA s =+ let (a,r) = break (== '\n') s+ in A.ModuleInlineAssembly a : takeModIA (dropWhile (== '\n') r)+ return $ takeModIA s+
+ src/LLVM/Internal/Instruction.hs view
@@ -0,0 +1,607 @@+{-# LANGUAGE+ TemplateHaskell,+ QuasiQuotes,+ MultiParamTypeClasses,+ UndecidableInstances,+ ViewPatterns+ #-}+module LLVM.Internal.Instruction where++import LLVM.Prelude++import qualified Language.Haskell.TH as TH+import qualified Language.Haskell.TH.Quote as TH+import qualified LLVM.Internal.InstructionDefs as ID+import LLVM.Internal.InstructionDefs (instrP)++import Control.Monad.AnyCont+import Control.Monad.Error.Class+import Control.Monad.IO.Class+import Control.Monad.State (gets)++import Foreign.Ptr++import Control.Exception (assert)+import qualified Data.Map as Map+import qualified Data.List as List+import Data.List.NonEmpty (NonEmpty((:|)))+import qualified Data.List.NonEmpty as NonEmpty++import qualified LLVM.Internal.FFI.PtrHierarchy as FFI+import qualified LLVM.Internal.FFI.BinaryOperator as FFI+import qualified LLVM.Internal.FFI.Instruction as FFI+import qualified LLVM.Internal.FFI.Value as FFI+import qualified LLVM.Internal.FFI.User as FFI+import qualified LLVM.Internal.FFI.Builder as FFI+import qualified LLVM.Internal.FFI.Constant as FFI+import qualified LLVM.Internal.FFI.BasicBlock as FFI++import LLVM.Internal.Atomicity ()+import LLVM.Internal.Attribute+import LLVM.Internal.CallingConvention ()+import LLVM.Internal.Coding+import LLVM.Internal.DecodeAST+import LLVM.Internal.EncodeAST+import LLVM.Internal.FastMathFlags ()+import LLVM.Internal.Metadata ()+import LLVM.Internal.Operand ()+import LLVM.Internal.RMWOperation ()+import LLVM.Internal.TailCallKind ()+import LLVM.Internal.Type+import LLVM.Internal.Value++import qualified LLVM.AST as A+import qualified LLVM.AST.Constant as A.C++callInstAttributeSet :: Ptr FFI.Instruction -> DecodeAST MixedAttributeSet+callInstAttributeSet = decodeM <=< liftIO . FFI.getCallSiteAttributeSet++meta :: Ptr FFI.Instruction -> DecodeAST A.InstructionMetadata+meta i = do+ let getMetadata n = scopeAnyCont $ do+ ks <- allocaArray n+ ps <- allocaArray n+ n' <- liftIO $ FFI.getMetadata i ks ps n+ if (n' > n) + then getMetadata n'+ else return zip `ap` decodeM (n', ks) `ap` decodeM (n', ps)+ getMetadata 4++setMD :: Ptr FFI.Instruction -> A.InstructionMetadata -> EncodeAST ()+setMD i md = forM_ md $ \(kindName, anode) -> do+ kindID <- encodeM kindName+ node <- encodeM anode+ liftIO $ FFI.setMetadata i kindID node++instance DecodeM DecodeAST A.Terminator (Ptr FFI.Instruction) where+ decodeM i = scopeAnyCont $ do+ n <- liftIO $ FFI.getInstructionDefOpcode i+ nOps <- liftIO $ FFI.getNumOperands (FFI.upCast i)+ md <- meta i+ let op n = decodeM =<< (liftIO $ FFI.getOperand (FFI.upCast i) n)+ successor n = decodeM =<< (liftIO $ FFI.isABasicBlock =<< FFI.getOperand (FFI.upCast i) n)+ case n of+ [instrP|Ret|] -> do+ returnOperand' <- if nOps == 0 then return Nothing else Just <$> op 0+ return $ A.Ret { A.returnOperand = returnOperand', A.metadata' = md }+ [instrP|Br|] -> do+ n <- liftIO $ FFI.getNumOperands (FFI.upCast i)+ case n of+ 1 -> do+ dest <- successor 0+ return $ A.Br { A.dest = dest, A.metadata' = md }+ 3 -> do+ condition <- op 0+ falseDest <- successor 1+ trueDest <- successor 2+ return $ A.CondBr {+ A.condition = condition,+ A.falseDest = falseDest, + A.trueDest = trueDest,+ A.metadata' = md+ }+ [instrP|Switch|] -> do+ op0 <- op 0+ dd <- successor 1+ let nCases = (nOps - 2) `div` 2+ values <- allocaArray nCases+ dests <- allocaArray nCases+ liftIO $ FFI.getSwitchCases i values dests+ cases <- return zip `ap` peekArray nCases values `ap` peekArray nCases dests+ dests <- forM cases $ \(c, d) -> return (,) `ap` decodeM c `ap` decodeM d+ return A.Switch {+ A.operand0' = op0,+ A.defaultDest = dd,+ A.dests = dests,+ A.metadata' = md+ }+ [instrP|IndirectBr|] -> do+ op0 <- op 0+ let nDests = nOps - 1+ dests <- allocaArray nDests+ liftIO $ FFI.getIndirectBrDests i dests+ dests <- decodeM (nDests, dests)+ return A.IndirectBr {+ A.operand0' = op0,+ A.possibleDests = dests,+ A.metadata' = md+ }+ [instrP|Invoke|] -> do+ cc <- decodeM =<< liftIO (FFI.getCallSiteCallingConvention i)+ attrs <- callInstAttributeSet i+ fv <- liftIO $ FFI.getCallSiteCalledValue i+ f <- decodeM fv+ args <- forM [1..nOps-3] $ \j -> do+ let pAttrs = Map.findWithDefault [] (j-1) (parameterAttributes attrs)+ return (, pAttrs) `ap` op (j-1) + rd <- successor (nOps - 2)+ ed <- successor (nOps - 1)+ return A.Invoke {+ A.callingConvention' = cc,+ A.returnAttributes' = returnAttributes attrs,+ A.function' = f,+ A.arguments' = args,+ A.functionAttributes' = functionAttributes attrs,+ A.returnDest = rd,+ A.exceptionDest = ed,+ A.metadata' = md+ }+ [instrP|Resume|] -> do+ op0 <- op 0+ return A.Resume {+ A.operand0' = op0,+ A.metadata' = md+ }+ [instrP|Unreachable|] -> do+ return A.Unreachable {+ A.metadata' = md+ }+ [instrP|CleanupRet|] -> do+ dest <- decodeM =<< liftIO (FFI.upCast <$> (FFI.getCleanupPad i) :: IO (Ptr FFI.Value))+ unwindDest <- decodeM =<< liftIO (FFI.getUnwindDest i)+ return A.CleanupRet {+ A.cleanupPad = dest,+ A.unwindDest = unwindDest,+ A.metadata' = md+ }+ [instrP|CatchRet|] -> do+ catchPad <- decodeM =<< liftIO (FFI.catchRetGetCatchPad i)+ successor <- decodeM =<< liftIO (FFI.catchRetGetSuccessor i)+ return A.CatchRet {+ A.catchPad = catchPad,+ A.successor = successor,+ A.metadata' = md+ }+ [instrP|CatchSwitch|] -> do+ parentPad' <- decodeM =<< liftIO (FFI.catchSwitchGetParentPad i)+ numHandlers <- liftIO (FFI.catchSwitchGetNumHandlers i)+ handlers <- assert (numHandlers > 0) $+ forM (0 :| [1..numHandlers - 1]) $ decodeM <=< liftIO . FFI.catchSwitchGetHandler i+ unwindDest <- decodeM =<< liftIO (FFI.catchSwitchGetUnwindDest i)+ return A.CatchSwitch {+ A.parentPad' = parentPad',+ A.catchHandlers = handlers,+ A.defaultUnwindDest = unwindDest,+ A.metadata' = md+ }++instance EncodeM EncodeAST A.Terminator (Ptr FFI.Instruction) where+ encodeM t = scopeAnyCont $ do+ builder <- gets encodeStateBuilder+ s <- encodeM ""+ t' <- case t of+ A.Ret { A.returnOperand = r } -> do+ rv <- maybe (return nullPtr) encodeM r+ FFI.upCast <$> do liftIO $ FFI.buildRet builder rv+ A.Br { A.dest = d } -> do+ db <- encodeM d+ FFI.upCast <$> do liftIO $ FFI.buildBr builder db+ A.CondBr { A.condition = c, A.trueDest = t, A.falseDest = f } -> do+ cv <- encodeM c+ tb <- encodeM t+ fb <- encodeM f+ FFI.upCast <$> do liftIO $ FFI.buildCondBr builder cv tb fb+ A.Switch {+ A.operand0' = op0,+ A.defaultDest = dd,+ A.dests = ds+ } -> do+ op0' <- encodeM op0+ dd' <- encodeM dd+ i <- liftIO $ FFI.buildSwitch builder op0' dd' (fromIntegral $ length ds)+ forM ds $ \(v,d) -> do+ v' <- encodeM v+ d' <- encodeM d+ liftIO $ FFI.addCase i v' d'+ return $ FFI.upCast i+ A.IndirectBr { + A.operand0' = op0,+ A.possibleDests = dests+ } -> do+ op0' <- encodeM op0+ i <- liftIO $ FFI.buildIndirectBr builder op0' (fromIntegral $ length dests)+ forM dests $ \dest -> do+ d <- encodeM dest+ liftIO $ FFI.addDestination i d+ return $ FFI.upCast i+ A.Invoke {+ A.callingConvention' = cc,+ A.returnAttributes' = rAttrs,+ A.function' = fun,+ A.arguments' = args,+ A.functionAttributes' = fAttrs,+ A.returnDest = rd,+ A.exceptionDest = ed+ } -> do+ fv <- encodeM fun+ rb <- encodeM rd+ eb <- encodeM ed+ let (argvs, argAttrs) = unzip args+ (n, argvs) <- encodeM argvs+ i <- liftIO $ FFI.buildInvoke builder fv argvs n rb eb s+ attrs <- encodeM $ MixedAttributeSet fAttrs rAttrs (Map.fromList (zip [0..] argAttrs))+ liftIO $ FFI.setCallSiteAttributeSet i attrs+ cc <- encodeM cc+ liftIO $ FFI.setCallSiteCallingConvention i cc+ return $ FFI.upCast i+ A.Resume { + A.operand0' = op0+ } -> do+ op0' <- encodeM op0+ i <- liftIO $ FFI.buildResume builder op0'+ return $ FFI.upCast i+ A.Unreachable {+ } -> do+ i <- liftIO $ FFI.buildUnreachable builder+ return $ FFI.upCast i+ A.CleanupRet {+ A.cleanupPad = cleanupPad,+ A.unwindDest = unwindDest+ } -> do+ cleanupPad' <- encodeM cleanupPad+ unwindDest' <- encodeM unwindDest+ liftIO $ FFI.buildCleanupRet builder cleanupPad' unwindDest'+ A.CatchRet {+ A.catchPad = catchPad,+ A.successor = successor+ } -> do+ catchPad' <- encodeM catchPad+ successor' <- encodeM successor+ liftIO $ FFI.buildCatchRet builder catchPad' successor'+ A.CatchSwitch {+ A.parentPad' = parentPad,+ A.catchHandlers = catchHandlers,+ A.defaultUnwindDest = unwindDest+ } -> do+ parentPad' <- encodeM parentPad+ unwindDest' <- encodeM unwindDest+ let numHandlers = fromIntegral (NonEmpty.length catchHandlers)+ i <- liftIO $ FFI.buildCatchSwitch builder parentPad' unwindDest' numHandlers+ mapM_ (liftIO . FFI.catchSwitchAddHandler i <=< encodeM) catchHandlers+ return i+ setMD t' (A.metadata' t)+ return t' ++$(do+ let findInstrFields s = Map.findWithDefault (error $ "instruction missing from AST: " ++ show s) s+ ID.astInstructionRecs++ [d|+ instance DecodeM DecodeAST A.Instruction (Ptr FFI.Instruction) where+ decodeM i = scopeAnyCont $ do+ t <- typeOf i+ nOps <- liftIO $ FFI.getNumOperands (FFI.upCast i)+ let op n = decodeM =<< (liftIO $ FFI.getOperand (FFI.upCast i) n)+ cop n = decodeM =<< (liftIO $ FFI.isAConstant =<< FFI.getOperand (FFI.upCast i) n)+ get_nsw b = liftIO $ decodeM =<< FFI.hasNoSignedWrap (FFI.upCast b)+ get_nuw b = liftIO $ decodeM =<< FFI.hasNoUnsignedWrap (FFI.upCast b)+ get_exact b = liftIO $ decodeM =<< FFI.isExact (FFI.upCast b)+ get_fastMathFlags b = liftIO $ decodeM =<< FFI.getFastMathFlags (FFI.upCast b)++ n <- liftIO $ FFI.getInstructionDefOpcode i+ $(+ let fieldDecoders :: String -> String -> ([String], TH.ExpQ)+ fieldDecoders lrn s = case s of+ "b" -> ([], [| liftIO $ FFI.isABinaryOperator (FFI.upCast i) |])+ "nsw" -> (["b"], [| get_nsw $(TH.dyn "b") |])+ "nuw" -> (["b"], [| get_nuw $(TH.dyn "b") |])+ "exact" -> (["b"], [| get_exact $(TH.dyn "b") |])+ "fastMathFlags" -> (["b"], [| get_fastMathFlags $(TH.dyn "b") |])+ "operand0" -> ([], [| op 0 |])+ "operand1" -> ([], [| op 1 |])+ "address" -> ([], case lrn of "Store" -> [| op 1 |]; _ -> [| op 0 |])+ "value" -> ([], case lrn of "Store" -> [| op 0 |]; _ -> [| op 1 |])+ "expected" -> ([], [| op 1 |])+ "replacement" -> ([], [| op 2 |])+ "condition'" -> ([], [| op 0 |])+ "trueValue" -> ([], [| op 1 |])+ "falseValue" -> ([], [| op 2 |])+ "argList" -> ([], [| op 0 |])+ "vector" -> ([], [| op 0 |])+ "element" -> ([], [| op 1 |])+ "index" -> ([], case lrn of "ExtractElement" -> [| op 1 |]; "InsertElement" -> [| op 2 |])+ "mask" -> ([], [| cop 2 |])+ "aggregate" -> ([], [| op 0 |])+ "metadata" -> ([], [| meta i |])+ "iPredicate" -> ([], [| decodeM =<< liftIO (FFI.getICmpPredicate i) |])+ "fpPredicate" -> ([], [| decodeM =<< liftIO (FFI.getFCmpPredicate i) |])+ "tailCallKind" -> ([], [| decodeM =<< liftIO (FFI.getTailCallKind i) |])+ "callingConvention" -> ([], [| decodeM =<< liftIO (FFI.getCallSiteCallingConvention i) |])+ "attrs" -> ([], [| callInstAttributeSet i |])+ "returnAttributes" -> (["attrs"], [| return $ returnAttributes $(TH.dyn "attrs") |])+ "f" -> ([], [| liftIO $ FFI.getCallSiteCalledValue i |])+ "function" -> (["f"], [| decodeM $(TH.dyn "f") |])+ "arguments" -> ([], [| forM [1..nOps-1] $ \j -> do+ let pAttrs = Map.findWithDefault [] (j-1) (parameterAttributes $(TH.dyn "attrs"))+ p <- op (j-1)+ return (p, pAttrs) |])+ "clauses" -> + ([], [|do+ nClauses <- liftIO $ FFI.getNumClauses i+ -- We need to convert nClauses to a signed+ -- value before subtracting+ forM [0..fromIntegral nClauses - (1 :: Int)] $ \j -> do+ v <- liftIO $ FFI.getClause i (fromIntegral j)+ c <- decodeM v+ t <- typeOf v+ return $ case t of { A.ArrayType _ _ -> A.Filter; _ -> A.Catch} $ c |])+ "functionAttributes" -> (["attrs"], [| return $ functionAttributes $(TH.dyn "attrs") |])+ "type'" -> ([], [| return t |])+ "incomingValues" ->+ ([], [| do+ n <- liftIO $ FFI.countIncoming i+ forM [0..n-1] $ \m -> do+ iv <- decodeM =<< (liftIO $ FFI.getIncomingValue i m)+ ib <- decodeM =<< (liftIO $ FFI.getIncomingBlock i m)+ return (iv,ib) |])+ "allocatedType" -> ([], [| decodeM =<< liftIO (FFI.getAllocatedType i) |])+ "numElements" -> + ([], [| do+ n <- decodeM =<< (liftIO $ FFI.getAllocaNumElements i)+ return $ case n of+ A.ConstantOperand (A.C.Int { A.C.integerValue = 1 }) -> Nothing+ _ -> Just n+ |]) + "alignment" -> ([], [| decodeM =<< liftIO (FFI.getInstrAlignment i) |])+ "maybeAtomicity" -> ([], [| decodeM =<< liftIO (FFI.getAtomicity i) |])+ "atomicity" -> ([], [| decodeM =<< liftIO (FFI.getAtomicity i) |])+ "volatile" -> ([], [| decodeM =<< liftIO (FFI.getVolatile i) |])+ "inBounds" -> ([], [| decodeM =<< liftIO (FFI.getInBounds (FFI.upCast i)) |])+ "failureMemoryOrdering" -> ([], [| decodeM =<< liftIO (FFI.getFailureAtomicOrdering i) |])+ "indices" -> ([], [| mapM op [1..nOps-1] |])+ "indices'" ->+ ([], [| do+ n <- liftIO $ FFI.countInstStructureIndices i+ a <- allocaArray n+ liftIO $ FFI.getInstStructureIndices i a+ decodeM (n, a) |])+ "rmwOperation" -> ([], [| decodeM =<< liftIO (FFI.getAtomicRMWBinOp i) |])+ "cleanup" -> ([], [| decodeM =<< liftIO (FFI.isCleanup i) |])+ "parentPad" -> ([], [| decodeM =<< liftIO (FFI.getParentPad i) |])+ "catchSwitch" -> ([], [| decodeM =<< liftIO (FFI.getParentPad i) |])+ "args" -> ([], [| do numArgs <- liftIO (FFI.getNumArgOperands i)+ if (numArgs == 0)+ then return []+ else forM [0..numArgs-1] $ \op ->+ decodeM =<< liftIO (FFI.getArgOperand i op) |])+ _ -> ([], [| error $ "unrecognized instruction field or depenency thereof: " ++ show s |])+ in+ TH.caseE [| n |] [+ TH.match opcodeP (TH.normalB (TH.doE handlerBody)) []+ | (lrn, iDef) <- Map.toList ID.instructionDefs,+ ID.instructionKind iDef /= ID.Terminator,+ let opcodeP = TH.dataToPatQ (const Nothing) (ID.cppOpcode iDef)+ handlerBody = + let TH.RecC fullName fields = findInstrFields lrn+ (fieldNames,_,_) = unzip3 fields+ allNames ns = List.nub $ [ d | n <- ns, d <- allNames . fst . fieldDecoders lrn $ n ] ++ ns+ in+ [ + TH.bindS (TH.varP (TH.mkName n)) (snd . fieldDecoders lrn $ n)+ | n <- allNames . map TH.nameBase $ fieldNames + ] ++ [ + TH.noBindS [| + return $(TH.recConE + fullName+ [ (f,) <$> (TH.varE . TH.mkName . TH.nameBase $ f) | f <- fieldNames ])+ |]+ ]+ ]+ )++ instance EncodeM EncodeAST A.Instruction (Ptr FFI.Instruction, EncodeAST ()) where+ encodeM o = scopeAnyCont $ do+ builder <- gets encodeStateBuilder+ let return' i = return (FFI.upCast i, return ())+ s <- encodeM ""+ (inst, act) <- case o of+ A.ICmp { + A.iPredicate = pred,+ A.operand0 = op0,+ A.operand1 = op1+ } -> do+ op0' <- encodeM op0+ op1' <- encodeM op1+ pred <- encodeM pred+ i <- liftIO $ FFI.buildICmp builder pred op0' op1' s+ return' i+ A.FCmp {+ A.fpPredicate = pred,+ A.operand0 = op0,+ A.operand1 = op1+ } -> do+ op0' <- encodeM op0+ op1' <- encodeM op1+ pred <- encodeM pred+ i <- liftIO $ FFI.buildFCmp builder pred op0' op1' s+ return' i+ A.Phi { A.type' = t, A.incomingValues = ivs } -> do+ t' <- encodeM t+ i <- liftIO $ FFI.buildPhi builder t' s+ return (+ FFI.upCast i,+ do+ let (ivs3, bs3) = unzip ivs+ ivs3' <- encodeM ivs3+ bs3' <- encodeM bs3+ liftIO $ FFI.addIncoming i ivs3' bs3'+ )+ A.Call {+ A.tailCallKind = tck,+ A.callingConvention = cc,+ A.returnAttributes = rAttrs,+ A.function = f,+ A.arguments = args,+ A.functionAttributes = fAttrs+ } -> do+ fv <- encodeM f+ let (argvs, argAttrs) = unzip args+ (n, argvs) <- encodeM argvs+ i <- liftIO $ FFI.buildCall builder fv argvs n s+ attrs <- encodeM $ MixedAttributeSet fAttrs rAttrs (Map.fromList (zip [0..] argAttrs))+ liftIO $ FFI.setCallSiteAttributeSet i attrs + tck <- encodeM tck+ liftIO $ FFI.setTailCallKind i tck+ cc <- encodeM cc+ liftIO $ FFI.setCallSiteCallingConvention i cc+ return' i+ A.Select { A.condition' = c, A.trueValue = t, A.falseValue = f } -> do+ c' <- encodeM c+ t' <- encodeM t+ f' <- encodeM f+ i <- liftIO $ FFI.buildSelect builder c' t' f' s+ return' i+ A.VAArg { A.argList = al, A.type' = t } -> do+ al' <- encodeM al+ t' <- encodeM t+ i <- liftIO $ FFI.buildVAArg builder al' t' s+ return' i+ A.ExtractElement { A.vector = v, A.index = idx } -> do+ v' <- encodeM v+ idx' <- encodeM idx+ i <- liftIO $ FFI.buildExtractElement builder v' idx' s+ return' i+ A.InsertElement { A.vector = v, A.element = e, A.index = idx } -> do+ v' <- encodeM v+ e' <- encodeM e+ idx' <- encodeM idx+ i <- liftIO $ FFI.buildInsertElement builder v' e' idx' s+ return' i+ A.ShuffleVector { A.operand0 = o0, A.operand1 = o1, A.mask = mask } -> do+ o0' <- encodeM o0+ o1' <- encodeM o1+ mask' <- encodeM mask+ i <- liftIO $ FFI.buildShuffleVector builder o0' o1' mask' s+ return' i+ A.ExtractValue { A.aggregate = a, A.indices' = is } -> do+ a' <- encodeM a+ (n, is') <- encodeM is+ i <- liftIO $ FFI.buildExtractValue builder a' is' n s+ return' i+ A.InsertValue { A.aggregate = a, A.element = e, A.indices' = is } -> do+ a' <- encodeM a+ e' <- encodeM e+ (n, is') <- encodeM is+ i <- liftIO $ FFI.buildInsertValue builder a' e' is' n s+ return' i+ A.LandingPad { + A.type' = t,+ A.cleanup = cl, + A.clauses = cs+ } -> do+ t' <- encodeM t+ i <- liftIO $ FFI.buildLandingPad builder t' (fromIntegral $ length cs) s+ forM cs $ \c -> + case c of+ A.Catch a -> do+ cn <- encodeM a+ isArray <- liftIO $ isArrayType =<< FFI.typeOf (FFI.upCast cn)+ when isArray $ throwError $ "Catch clause cannot take an array: " ++ show c+ liftIO $ FFI.addClause i cn+ A.Filter a -> do+ cn <- encodeM a+ isArray <- liftIO $ isArrayType =<< FFI.typeOf (FFI.upCast cn)+ unless isArray $ throwError $ "filter clause must take an array: " ++ show c+ liftIO $ FFI.addClause i cn+ when cl $ do+ cl <- encodeM cl+ liftIO $ FFI.setCleanup i cl+ return' i+ A.Alloca { A.allocatedType = alt, A.numElements = n, A.alignment = alignment } -> do + alt' <- encodeM alt+ n' <- encodeM n+ i <- liftIO $ FFI.buildAlloca builder alt' n' s+ unless (alignment == 0) $ liftIO $ FFI.setInstrAlignment i (fromIntegral alignment)+ return' i+ A.CleanupPad { A.parentPad = parentPad, A.args = args } -> do+ parentPad' <- encodeM parentPad+ (numArgs, args') <- encodeM args+ i <- liftIO $ FFI.buildCleanupPad builder parentPad' args' numArgs s+ return' i+ A.CatchPad { A.catchSwitch = catchSwitch, A.args = args } -> do+ catchSwitch' <- encodeM catchSwitch+ (numArgs, args') <- encodeM args+ i <- liftIO $ FFI.buildCatchPad builder catchSwitch' args' numArgs s+ return' i+ o -> $(TH.caseE [| o |] [+ TH.match + (TH.recP fullName [ (f,) <$> (TH.varP . TH.mkName . TH.nameBase $ f) | f <- fieldNames ])+ (TH.normalB (TH.doE handlerBody))+ []+ |+ (name, ID.instructionKind -> k) <- Map.toList ID.instructionDefs,+ case (k, name) of+ (ID.Binary, _) -> True+ (ID.Cast, _) -> True+ (ID.Memory, "Alloca") -> False+ (ID.Memory, _) -> True+ _ -> False,+ let+ TH.RecC fullName (unzip3 -> (fieldNames, _, _)) = findInstrFields name+ encodeMFields = map TH.nameBase fieldNames List.\\ [ "metadata" ]+ handlerBody = ([+ TH.bindS (if s == "fastMathFlags" then TH.tupP [] else TH.varP (TH.mkName s))+ [| encodeM $(TH.dyn s) |] | s <- encodeMFields + ] ++ [+ TH.bindS (TH.varP (TH.mkName "i")) [| liftIO $ $(+ foldl1 TH.appE . map TH.dyn $ + [ "FFI.build" ++ name, "builder" ] ++ (encodeMFields List.\\ [ "fastMathFlags" ]) ++ [ "s" ] + ) |],+ TH.noBindS [| return' $(TH.dyn "i") |]+ ])+ ]+ )++ setMD inst (A.metadata o)+ return (inst, act)+ |]+ )+++instance DecodeM DecodeAST a (Ptr FFI.Instruction) => DecodeM DecodeAST (DecodeAST (A.Named a)) (Ptr FFI.Instruction) where+ decodeM i = do+ t <- typeOf i+ w <- if t == A.VoidType then (return A.Do) else (return (A.:=) `ap` getLocalName i)+ return $ return w `ap` decodeM i++instance EncodeM EncodeAST a (Ptr FFI.Instruction) => EncodeM EncodeAST (A.Named a) (Ptr FFI.Instruction) where+ encodeM (A.Do o) = encodeM o+ encodeM (n A.:= o) = do+ i <- encodeM o+ let v = FFI.upCast i+ n' <- encodeM n+ liftIO $ FFI.setValueName v n'+ defineLocal n v+ return i++instance EncodeM EncodeAST a (Ptr FFI.Instruction, EncodeAST ()) => EncodeM EncodeAST (A.Named a) (EncodeAST ()) where+ encodeM (A.Do o) = liftM snd $ (encodeM o :: EncodeAST (Ptr FFI.Instruction, EncodeAST ()))+ encodeM (n A.:= o) = do+ (i, later) <- encodeM o+ let v = FFI.upCast (i :: Ptr FFI.Instruction)+ n' <- encodeM n+ liftIO $ FFI.setValueName v n'+ defineLocal n v+ return later++
+ src/LLVM/Internal/InstructionDefs.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE+ TemplateHaskell,+ CPP+ #-}+module LLVM.Internal.InstructionDefs (+ astInstructionRecs,+ astConstantRecs,+ instructionDefs,+ ID.InstructionKind(..),+ ID.InstructionDef(..),+ instrP,+ innerJoin,+ outerJoin+ ) where++import LLVM.Prelude++import qualified Language.Haskell.TH as TH+import qualified Language.Haskell.TH.Quote as TH++import Data.Map (Map)+import qualified Data.Map as Map++import qualified LLVM.Internal.FFI.InstructionDefs as ID++import qualified LLVM.AST.Instruction as A+import qualified LLVM.AST.Constant as A.C++$(do+ let ctorRecs t = do+#if __GLASGOW_HASKELL__ < 800+ TH.TyConI (TH.DataD _ _ _ cons _) <- TH.reify t+#else+ TH.TyConI (TH.DataD _ _ _ _ cons _) <- TH.reify t+#endif+ TH.dataToExpQ (const Nothing) $ [ (TH.nameBase n, rec) | rec@(TH.RecC n _) <- cons ]++ [d|+ astInstructionRecs :: Map String TH.Con+ astInstructionRecs = Map.fromList $(ctorRecs ''A.Instruction)+ astConstantRecs :: Map String TH.Con+ astConstantRecs = Map.fromList $(ctorRecs ''A.C.Constant)+ |]+ )++instructionDefs :: Map String ID.InstructionDef+instructionDefs = Map.fromList [ ((refName . ID.cAPIName $ i), i) | i <- ID.instructionDefs ]+ where+ refName "AtomicCmpXchg" = "CmpXchg"+ refName "PHI" = "Phi"+ refName x = x++innerJoin :: Ord k => Map k a -> Map k b -> Map k (a,b)+innerJoin = Map.intersectionWith (,)++outerJoin :: Ord k => Map k a -> Map k b -> Map k (Maybe a, Maybe b)+outerJoin xs ys = Map.unionWith combine+ (Map.map (\a -> (Just a, Nothing)) xs)+ (Map.map (\b -> (Nothing, Just b)) ys)+ where+ combine (Just a, Nothing) (Nothing, Just b) = (Just a, Just b)+ combine _ _ = error "outerJoin: the impossible happened"++instrP :: TH.QuasiQuoter+instrP = TH.QuasiQuoter {+ TH.quoteExp = undefined,+ TH.quotePat = let m = Map.fromList [ (ID.cAPIName i, ID.cppOpcode i) | i <- ID.instructionDefs ]+ in TH.dataToPatQ (const Nothing) . (m Map.!),+ TH.quoteType = undefined,+ TH.quoteDec = undefined+ }
+ src/LLVM/Internal/IntegerPredicate.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE+ TemplateHaskell,+ MultiParamTypeClasses+ #-}+module LLVM.Internal.IntegerPredicate where++import LLVM.Internal.Coding++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import qualified LLVM.AST.IntegerPredicate as A.IPred++genCodingInstance [t| A.IPred.IntegerPredicate |] ''FFI.ICmpPredicate [+ (FFI.iCmpPredEQ, A.IPred.EQ),+ (FFI.iCmpPredNE, A.IPred.NE),+ (FFI.iCmpPredUGT, A.IPred.UGT),+ (FFI.iCmpPredUGE, A.IPred.UGE),+ (FFI.iCmpPredULT, A.IPred.ULT),+ (FFI.iCmpPredULE, A.IPred.ULE),+ (FFI.iCmpPredSGT, A.IPred.SGT),+ (FFI.iCmpPredSGE, A.IPred.SGE),+ (FFI.iCmpPredSLT, A.IPred.SLT),+ (FFI.iCmpPredSLE, A.IPred.SLE)+ ]
+ src/LLVM/Internal/LibraryFunction.hsc view
@@ -0,0 +1,37 @@+{-# LANGUAGE+ MultiParamTypeClasses+ #-}+module LLVM.Internal.LibraryFunction where++import LLVM.Prelude++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI++import LLVM.Internal.Coding++#include "LLVM/Internal/FFI/LibFunc.h"++#{+define hsc_inject(m) { \+ struct { const char *s; unsigned n; } *p, list[] = { LLVM_HS_FOR_EACH_LIB_FUNC(m) }; \+ hsc_printf("data LibraryFunction\n"); \+ for(p = list; p < list + sizeof(list)/sizeof(list[0]); ++p) { \+ hsc_printf(" %s LF__%s\n", (p == list ? "=" : "|"), p->s); \+ } \+ hsc_printf(" deriving (Eq, Ord, Enum, Bounded, Read, Show)"); \+ hsc_printf("\n"); \+ hsc_printf("instance Monad m => EncodeM m LibraryFunction FFI.LibFunc where\n"); \+ for(p = list; p < list + sizeof(list)/sizeof(list[0]); ++p) { \+ hsc_printf(" encodeM LF__%s = return (FFI.LibFunc %u)\n", p->s, p->n); \+ } \+ hsc_printf("\n"); \+ hsc_printf("instance Monad m => DecodeM m LibraryFunction FFI.LibFunc where\n"); \+ for(p = list; p < list + sizeof(list)/sizeof(list[0]); ++p) { \+ hsc_printf(" decodeM (FFI.LibFunc %u) = return LF__%s \n", p->n, p->s); \+ } \+}+}++-- | <http://llvm.org/doxygen/namespacellvm_1_1LibFunc.html#abf8f6830387f338fed0bce2e65108c6f>+#define Mac(n) { #n, LLVMLibFunc__ ## n },+#{inject Mac}
+ src/LLVM/Internal/MemoryBuffer.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+module LLVM.Internal.MemoryBuffer where++import LLVM.Prelude++import Control.Exception+import Control.Monad.AnyCont+import Control.Monad.Error.Class+import Control.Monad.IO.Class+import qualified Data.ByteString as BS+import qualified Data.ByteString.Unsafe as BS+import Foreign.Ptr++import LLVM.Internal.Coding+import LLVM.Internal.String+import LLVM.Internal.Inject+import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import qualified LLVM.Internal.FFI.MemoryBuffer as FFI++data Specification + = Bytes { name :: String, content :: BS.ByteString }+ | File { pathName :: String }++instance (Inject String e, MonadError e m, Monad m, MonadIO m, MonadAnyCont IO m) => EncodeM m Specification (FFI.OwnerTransfered (Ptr FFI.MemoryBuffer)) where+ encodeM spec = liftM FFI.OwnerTransfered $ do+ case spec of+ Bytes name content -> do+ (s,l) <- anyContToM $ BS.unsafeUseAsCStringLen (BS.snoc content 0)+ name <- encodeM name+ nullTerminate <- encodeM True+ liftIO $ FFI.createMemoryBufferWithMemoryRange s (fromIntegral (l-1)) name nullTerminate+ File pathName -> do+ pathName <- encodeM pathName+ mbPtr <- alloca+ msgPtr <- alloca+ result <- decodeM =<< (liftIO $ FFI.createMemoryBufferWithContentsOfFile pathName mbPtr msgPtr)+ when result $ do+ msg <- decodeM msgPtr+ throwError (inject (msg :: String))+ peek mbPtr ++instance (Inject String e, MonadError e m, Monad m, MonadIO m, MonadAnyCont IO m) => EncodeM m Specification (Ptr FFI.MemoryBuffer) where+ encodeM spec = do+ FFI.OwnerTransfered mb <- encodeM spec+ anyContToM $ bracket (return mb) FFI.disposeMemoryBuffer++instance MonadIO d => DecodeM d BS.ByteString (Ptr FFI.MemoryBuffer) where+ decodeM p = do+ s <- liftIO $ FFI.getBufferStart p+ l <- liftIO $ FFI.getBufferSize p+ liftIO $ BS.packCStringLen (s, fromIntegral l)++instance MonadIO d => DecodeM d String (Ptr FFI.MemoryBuffer) where+ decodeM = decodeM . UTF8ByteString <=< decodeM
+ src/LLVM/Internal/Metadata.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE+ MultiParamTypeClasses+ #-}+module LLVM.Internal.Metadata where++import LLVM.Prelude++import Control.Monad.State hiding (mapM, forM)+import Control.Monad.AnyCont++import Foreign.Ptr++import qualified Foreign.Marshal.Array as FMA+import qualified Data.Array as Array++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import qualified LLVM.Internal.FFI.Metadata as FFI+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI++import LLVM.Internal.Context+import LLVM.Internal.Coding+import LLVM.Internal.EncodeAST+import LLVM.Internal.DecodeAST+import LLVM.Internal.Value ()++instance EncodeM EncodeAST String FFI.MDKindID where+ encodeM s = do+ Context c <- gets encodeStateContext+ s <- encodeM s+ liftIO $ FFI.getMDKindIDInContext c s++getMetadataKindNames :: Context -> DecodeAST ()+getMetadataKindNames (Context c) = scopeAnyCont $ do+ let g n = do+ ps <- allocaArray n+ ls <- allocaArray n + n' <- liftIO $ FFI.getMDKindNames c ps ls n+ if n' > n+ then g n'+ else do+ csls <- return zip+ `ap` liftIO (FMA.peekArray (fromIntegral n') ps)+ `ap` liftIO (FMA.peekArray (fromIntegral n') ls)+ mapM decodeM csls+ strs <- g 16+ modify $ \s -> s { metadataKinds = Array.listArray (0, fromIntegral (length strs) - 1) strs }++instance DecodeM DecodeAST String FFI.MDKindID where+ decodeM (FFI.MDKindID k) = gets $ (Array.! (fromIntegral k)) . metadataKinds++instance DecodeM DecodeAST String (Ptr FFI.MDString) where+ decodeM p = do+ np <- alloca+ s <- liftIO $ FFI.getMDString p np+ n <- peek np+ decodeM (s, n)
+ src/LLVM/Internal/Module.hs view
@@ -0,0 +1,526 @@+{-#+ LANGUAGE+ TemplateHaskell,+ ScopedTypeVariables,+ MultiParamTypeClasses+ #-}+-- | This Haskell module is for/of functions for handling LLVM modules.+module LLVM.Internal.Module where++import LLVM.Prelude++import Control.Exception+import Control.Monad.AnyCont+import Control.Monad.Error.Class+import Control.Monad.Trans.Except+import Control.Monad.State (gets)+import Control.Monad.Trans++import Foreign.Ptr+import Foreign.C+import Data.IORef+import qualified Data.ByteString as BS+import qualified Data.Map as Map++import qualified LLVM.Internal.FFI.Assembly as FFI+import qualified LLVM.Internal.FFI.Builder as FFI+import qualified LLVM.Internal.FFI.Bitcode as FFI+import qualified LLVM.Internal.FFI.Function as FFI+import qualified LLVM.Internal.FFI.GlobalAlias as FFI+import qualified LLVM.Internal.FFI.GlobalValue as FFI+import qualified LLVM.Internal.FFI.GlobalVariable as FFI+import qualified LLVM.Internal.FFI.Iterate as FFI+import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import qualified LLVM.Internal.FFI.MemoryBuffer as FFI+import qualified LLVM.Internal.FFI.Metadata as FFI+import qualified LLVM.Internal.FFI.Module as FFI+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI+import qualified LLVM.Internal.FFI.RawOStream as FFI+import qualified LLVM.Internal.FFI.Target as FFI+import qualified LLVM.Internal.FFI.Value as FFI++import LLVM.Internal.Attribute+import LLVM.Internal.BasicBlock +import LLVM.Internal.Coding+import LLVM.Internal.Context+import LLVM.Internal.DecodeAST+import LLVM.Internal.EncodeAST+import LLVM.Internal.Function+import LLVM.Internal.Global+import LLVM.Internal.Inject+import LLVM.Internal.Instruction ()+import qualified LLVM.Internal.MemoryBuffer as MB+import LLVM.Internal.Metadata+import LLVM.Internal.Operand+import LLVM.Internal.RawOStream+import LLVM.Internal.String+import LLVM.Internal.Target+import LLVM.Internal.Type+import LLVM.Internal.Value++import LLVM.DataLayout+import LLVM.Diagnostic++import qualified LLVM.AST as A+import qualified LLVM.AST.DataLayout as A+import qualified LLVM.AST.AddrSpace as A+import qualified LLVM.AST.Global as A.G++-- | <http://llvm.org/doxygen/classllvm_1_1Module.html>+newtype Module = Module (IORef (Ptr FFI.Module))++newModule :: Ptr FFI.Module -> IO (Module)+newModule m = fmap Module (newIORef m)++readModule :: MonadIO m => Module -> m (Ptr FFI.Module)+readModule (Module ref) = liftIO $ readIORef ref++-- | Signal that a module does no longer exist and thus must not be+-- disposed. It is the responsibility of the caller to ensure that the+-- module has been disposed. If you use only the functions provided by+-- llvm-hs you should never call this yourself.+deleteModule :: Module -> IO ()+deleteModule (Module r) = writeIORef r nullPtr++-- | A newtype to distinguish strings used for paths from other strings+newtype File = File FilePath+ deriving (Eq, Ord, Read, Show)++instance Inject String (Either String Diagnostic) where+ inject = Left++-- | link LLVM modules - move or copy parts of a source module into a+-- destination module. Note that this operation is not commutative -+-- not only concretely (e.g. the destination module is modified,+-- becoming the result) but abstractly (e.g. unused private globals in+-- the source module do not appear in the result, but similar globals+-- in the destination remain). The source module is destroyed.+linkModules ::+ Module -- ^ The module into which to link+ -> Module -- ^ The module to link into the other (this module is destroyed)+ -> ExceptT String IO ()+linkModules dest src = flip runAnyContT return $ do+ dest' <- readModule dest+ src' <- readModule src+ result <- decodeM =<< liftIO (FFI.linkModules dest' src')+ -- linkModules takes care of deleting the sourcemodule+ liftIO $ deleteModule src+ when result (throwError "Couldn’t link modules")++class LLVMAssemblyInput s where+ llvmAssemblyMemoryBuffer :: (Inject String e, MonadError e m, MonadIO m, MonadAnyCont IO m)+ => s -> m (FFI.OwnerTransfered (Ptr FFI.MemoryBuffer))++instance LLVMAssemblyInput (String, String) where+ llvmAssemblyMemoryBuffer (id, s) = do+ UTF8ByteString bs <- encodeM s+ encodeM (MB.Bytes id bs)++instance LLVMAssemblyInput String where+ llvmAssemblyMemoryBuffer s = llvmAssemblyMemoryBuffer ("<string>", s)++instance LLVMAssemblyInput File where+ llvmAssemblyMemoryBuffer (File p) = encodeM (MB.File p)++-- | parse 'Module' from LLVM assembly+withModuleFromLLVMAssembly :: LLVMAssemblyInput s+ => Context -> s -> (Module -> IO a) -> ExceptT String IO a+withModuleFromLLVMAssembly (Context c) s f = flip runAnyContT return $ do+ mb <- llvmAssemblyMemoryBuffer s+ msgPtr <- alloca+ m <- anyContToM $ bracket (newModule =<< FFI.parseLLVMAssembly c mb msgPtr) (FFI.disposeModule <=< readModule)+ m' <- readModule m+ when (m' == nullPtr) $ throwError =<< decodeM msgPtr+ liftIO $ f m++-- | generate LLVM assembly from a 'Module'+moduleLLVMAssembly :: Module -> IO String+moduleLLVMAssembly m = do+ resultRef <- newIORef Nothing+ let saveBuffer :: Ptr CChar -> CSize -> IO ()+ saveBuffer start size = do+ r <- decodeM (start, fromIntegral size)+ writeIORef resultRef (Just r)+ m' <- readModule m+ FFI.withBufferRawPWriteStream saveBuffer $ FFI.writeLLVMAssembly m' . FFI.upCast+ Just s <- readIORef resultRef+ return s++-- | write LLVM assembly for a 'Module' to a file+writeLLVMAssemblyToFile :: File -> Module -> ExceptT String IO ()+writeLLVMAssemblyToFile (File path) m = flip runAnyContT return $ do+ m' <- readModule m+ withFileRawOStream path False True $ liftIO . (FFI.writeLLVMAssembly m')++class BitcodeInput b where+ bitcodeMemoryBuffer :: (Inject String e, MonadError e m, MonadIO m, MonadAnyCont IO m)+ => b -> m (Ptr FFI.MemoryBuffer)++instance BitcodeInput (String, BS.ByteString) where+ bitcodeMemoryBuffer (s, bs) = encodeM (MB.Bytes s bs)++instance BitcodeInput File where+ bitcodeMemoryBuffer (File p) = encodeM (MB.File p)++-- | parse 'Module' from LLVM bitcode+withModuleFromBitcode :: BitcodeInput b => Context -> b -> (Module -> IO a) -> ExceptT String IO a+withModuleFromBitcode (Context c) b f = flip runAnyContT return $ do+ mb <- bitcodeMemoryBuffer b+ msgPtr <- alloca+ m <- anyContToM $ bracket (newModule =<< FFI.parseBitcode c mb msgPtr) (FFI.disposeModule <=< readModule)+ m' <- readModule m+ when (m' == nullPtr) $ throwError =<< decodeM msgPtr+ liftIO $ f m++-- | generate LLVM bitcode from a 'Module'+moduleBitcode :: Module -> IO BS.ByteString+moduleBitcode m = do+ m' <- readModule m+ r <- runExceptT $ withBufferRawOStream (liftIO . FFI.writeBitcode m')+ either fail return r++-- | write LLVM bitcode from a 'Module' into a file+writeBitcodeToFile :: File -> Module -> ExceptT String IO ()+writeBitcodeToFile (File path) m = flip runAnyContT return $ do+ m' <- readModule m+ withFileRawOStream path False False $ liftIO . FFI.writeBitcode m'++targetMachineEmit :: FFI.CodeGenFileType -> TargetMachine -> Module -> Ptr FFI.RawPWriteStream -> ExceptT String IO ()+targetMachineEmit fileType (TargetMachine tm) m os = flip runAnyContT return $ do+ msgPtr <- alloca+ m' <- readModule m+ r <- decodeM =<< (liftIO $ FFI.targetMachineEmit tm m' os fileType msgPtr)+ when r $ throwError =<< decodeM msgPtr++emitToFile :: FFI.CodeGenFileType -> TargetMachine -> File -> Module -> ExceptT String IO ()+emitToFile fileType tm (File path) m = flip runAnyContT return $ do+ withFileRawPWriteStream path False False $ targetMachineEmit fileType tm m++emitToByteString :: FFI.CodeGenFileType -> TargetMachine -> Module -> ExceptT String IO BS.ByteString+emitToByteString fileType tm m = flip runAnyContT return $ do+ withBufferRawPWriteStream $ targetMachineEmit fileType tm m++-- | write target-specific assembly directly into a file+writeTargetAssemblyToFile :: TargetMachine -> File -> Module -> ExceptT String IO ()+writeTargetAssemblyToFile = emitToFile FFI.codeGenFileTypeAssembly++-- | produce target-specific assembly as a 'String'+moduleTargetAssembly :: TargetMachine -> Module -> ExceptT String IO String+moduleTargetAssembly tm m = decodeM . UTF8ByteString =<< emitToByteString FFI.codeGenFileTypeAssembly tm m++-- | produce target-specific object code as a 'ByteString'+moduleObject :: TargetMachine -> Module -> ExceptT String IO BS.ByteString+moduleObject = emitToByteString FFI.codeGenFileTypeObject++-- | write target-specific object code directly into a file+writeObjectToFile :: TargetMachine -> File -> Module -> ExceptT String IO ()+writeObjectToFile = emitToFile FFI.codeGenFileTypeObject++setTargetTriple :: Ptr FFI.Module -> String -> EncodeAST ()+setTargetTriple m t = do+ t <- encodeM t+ liftIO $ FFI.setTargetTriple m t++getTargetTriple :: Ptr FFI.Module -> IO (Maybe String)+getTargetTriple m = do+ s <- decodeM =<< liftIO (FFI.getTargetTriple m)+ return $ if s == "" then Nothing else Just s++setDataLayout :: Ptr FFI.Module -> A.DataLayout -> EncodeAST ()+setDataLayout m dl = do+ s <- encodeM (dataLayoutToString dl)+ liftIO $ FFI.setDataLayout m s++getDataLayout :: Ptr FFI.Module -> IO (Maybe A.DataLayout)+getDataLayout m = do+ dlString <- decodeM =<< FFI.getDataLayout m+ either fail return . runExcept . parseDataLayout A.BigEndian $ dlString++-- | This function will call disposeModule after the callback+-- exits. Calling 'deleteModule' prevents double free errors. As long+-- as you only call functions provided by llvm-hs this should not+-- be necessary since llvm-hs takes care of this.+withModuleFromAST :: Context -> A.Module -> (Module -> IO a) -> ExceptT String IO a+withModuleFromAST context@(Context c) (A.Module moduleId sourceFileName dataLayout triple definitions) f = runEncodeAST context $ do+ moduleId <- encodeM moduleId+ m <- anyContToM $ bracket (newModule =<< FFI.moduleCreateWithNameInContext moduleId c) (FFI.disposeModule <=< readModule)+ ffiMod <- readModule m+ sourceFileName' <- encodeM sourceFileName+ liftIO $ FFI.setSourceFileName ffiMod sourceFileName'+ Context context <- gets encodeStateContext+ maybe (return ()) (setDataLayout ffiMod) dataLayout+ maybe (return ()) (setTargetTriple ffiMod) triple+ let sequencePhases :: EncodeAST [EncodeAST (EncodeAST (EncodeAST (EncodeAST ())))] -> EncodeAST ()+ sequencePhases l = (l >>= (sequence >=> sequence >=> sequence >=> sequence)) >> (return ())+ sequencePhases $ forM definitions $ \d -> case d of+ A.TypeDefinition n t -> do+ t' <- createNamedType n+ defineType n t'+ return $ do+ maybe (return ()) (setNamedType t') t+ return . return . return . return $ ()++ A.COMDAT n csk -> do+ n' <- encodeM n+ csk <- encodeM csk+ cd <- liftIO $ FFI.getOrInsertCOMDAT ffiMod n'+ liftIO $ FFI.setCOMDATSelectionKind cd csk+ defineCOMDAT n cd+ return . return . return . return . return $ ()+ + A.MetadataNodeDefinition i os -> return . return $ do+ t <- liftIO $ FFI.createTemporaryMDNodeInContext context+ defineMDNode i t+ return $ do+ n <- encodeM (A.MetadataNode os)+ liftIO $ FFI.metadataReplaceAllUsesWith (FFI.upCast t) (FFI.upCast n)+ defineMDNode i n+ return $ return ()++ A.NamedMetadataDefinition n ids -> return . return . return . return $ do+ n <- encodeM n+ ids <- encodeM (map A.MetadataNodeReference ids)+ nm <- liftIO $ FFI.getOrAddNamedMetadata ffiMod n+ liftIO $ FFI.namedMetadataAddOperands nm ids+ return ()++ A.ModuleInlineAssembly s -> do+ s <- encodeM s+ liftIO $ FFI.moduleAppendInlineAsm ffiMod (FFI.ModuleAsm s)+ return . return . return . return . return $ ()++ A.FunctionAttributes gid attrs -> do+ attrs <- encodeM attrs+ defineAttributeGroup gid attrs+ return . return . return . return . return $ ()++ A.GlobalDefinition g -> return . phase $ do+ eg' :: EncodeAST (Ptr FFI.GlobalValue) <- case g of+ g@(A.GlobalVariable { A.G.name = n }) -> do+ typ <- encodeM (A.G.type' g)+ g' <- liftIO $ withName n $ \gName ->+ FFI.addGlobalInAddressSpace ffiMod typ gName+ (fromIntegral ((\(A.AddrSpace a) -> a) $ A.G.addrSpace g))+ defineGlobal n g'+ setThreadLocalMode g' (A.G.threadLocalMode g)+ liftIO $ do+ hua <- encodeM (A.G.unnamedAddr g)+ FFI.setUnnamedAddr (FFI.upCast g') hua+ ic <- encodeM (A.G.isConstant g)+ FFI.setGlobalConstant g' ic+ return $ do+ maybe (return ()) ((liftIO . FFI.setInitializer g') <=< encodeM) (A.G.initializer g)+ setSection g' (A.G.section g)+ setCOMDAT g' (A.G.comdat g)+ setAlignment g' (A.G.alignment g)+ return (FFI.upCast g')+ (a@A.G.GlobalAlias { A.G.name = n }) -> do+ let A.PointerType typ as = A.G.type' a+ typ <- encodeM typ+ as <- encodeM as+ a' <- liftIO $ withName n $ \name -> FFI.justAddAlias ffiMod typ as name+ defineGlobal n a'+ liftIO $ do+ hua <- encodeM (A.G.unnamedAddr a)+ FFI.setUnnamedAddr (FFI.upCast a') hua+ return $ do+ setThreadLocalMode a' (A.G.threadLocalMode a)+ (liftIO . FFI.setAliasee a') =<< encodeM (A.G.aliasee a)+ return (FFI.upCast a')+ (A.Function _ _ _ cc rAttrs resultType fName (args, isVarArgs) attrs _ _ _ gc prefix blocks personality) -> do+ typ <- encodeM $ A.FunctionType resultType [t | A.Parameter t _ _ <- args] isVarArgs+ f <- liftIO . withName fName $ \fName -> FFI.addFunction ffiMod fName typ+ defineGlobal fName f+ cc <- encodeM cc+ liftIO $ FFI.setFunctionCallingConvention f cc+ setFunctionAttributes f (MixedAttributeSet attrs rAttrs (Map.fromList $ zip [0..] [pa | A.Parameter _ _ pa <- args]))+ setPrefixData f prefix+ setSection f (A.G.section g)+ setCOMDAT f (A.G.comdat g)+ setAlignment f (A.G.alignment g)+ setGC f gc+ setPersonalityFn f personality+ forM blocks $ \(A.BasicBlock bName _ _) -> do+ b <- liftIO $ withName bName $ \bName -> FFI.appendBasicBlockInContext context f bName+ defineBasicBlock fName bName b+ phase $ do+ let nParams = length args+ ps <- allocaArray nParams+ liftIO $ FFI.getParams f ps+ params <- peekArray nParams ps+ forM (zip args params) $ \(A.Parameter _ n _, p) -> do+ defineLocal n p+ n <- encodeM n+ liftIO $ FFI.setValueName (FFI.upCast p) n+ finishInstrs <- forM blocks $ \(A.BasicBlock bName namedInstrs term) -> do+ b <- encodeM bName+ (do+ builder <- gets encodeStateBuilder+ liftIO $ FFI.positionBuilderAtEnd builder b)+ finishes <- mapM encodeM namedInstrs :: EncodeAST [EncodeAST ()]+ (encodeM term :: EncodeAST (Ptr FFI.Instruction))+ return (sequence_ finishes)+ sequence_ finishInstrs+ locals <- gets $ Map.toList . encodeStateLocals+ forM [ n | (n, ForwardValue _) <- locals ] $ \n -> undefinedReference "local" n+ return (FFI.upCast f)+ return $ do+ g' <- eg'+ setLinkage g' (A.G.linkage g)+ setVisibility g' (A.G.visibility g)+ setDLLStorageClass g' (A.G.dllStorageClass g)+ return $ return ()+ liftIO $ f m+++-- This returns a nested DecodeAST to allow interleaving of different+-- decoding steps. Take a look at the call site in moduleAST for more+-- details.+decodeGlobalVariables :: Ptr FFI.Module -> DecodeAST (DecodeAST [A.G.Global])+decodeGlobalVariables mod = do+ ffiGlobals <- liftIO $ FFI.getXs (FFI.getFirstGlobal mod) FFI.getNextGlobal+ fmap sequence . forM ffiGlobals $ \g -> do+ A.PointerType t as <- typeOf g+ n <- getGlobalName g+ return $+ A.GlobalVariable+ <$> return n+ <*> getLinkage g+ <*> getVisibility g+ <*> getDLLStorageClass g+ <*> getThreadLocalMode g+ <*> return as+ <*> (liftIO $ decodeM =<< FFI.getUnnamedAddr (FFI.upCast g))+ <*> (liftIO $ decodeM =<< FFI.isGlobalConstant g)+ <*> return t+ <*> (do i <- liftIO $ FFI.getInitializer g+ if i == nullPtr+ then return Nothing+ else Just <$> decodeM i)+ <*> getSection g+ <*> getCOMDATName g+ <*> getAlignment g++-- This returns a nested DecodeAST to allow interleaving of different+-- decoding steps. Take a look at the call site in moduleAST for more+-- details.+decodeGlobalAliases :: Ptr FFI.Module -> DecodeAST (DecodeAST [A.G.Global])+decodeGlobalAliases mod = do+ ffiAliases <- liftIO $ FFI.getXs (FFI.getFirstAlias mod) FFI.getNextAlias+ fmap sequence . forM ffiAliases $ \a -> do+ n <- getGlobalName a+ return $+ A.G.GlobalAlias+ <$> return n+ <*> getLinkage a+ <*> getVisibility a+ <*> getDLLStorageClass a+ <*> getThreadLocalMode a+ <*> (liftIO $ decodeM =<< FFI.getUnnamedAddr (FFI.upCast a))+ <*> typeOf a+ <*> (decodeM =<< (liftIO $ FFI.getAliasee a))++-- This returns a nested DecodeAST to allow interleaving of different+-- decoding steps. Take a look at the call site in moduleAST for more+-- details.+decodeFunctions :: Ptr FFI.Module -> DecodeAST (DecodeAST [A.G.Global])+decodeFunctions mod = do+ ffiFunctions <-+ liftIO $ FFI.getXs (FFI.getFirstFunction mod) FFI.getNextFunction+ fmap sequence . forM ffiFunctions $ \f ->+ localScope $ do+ A.PointerType (A.FunctionType returnType _ isVarArg) _ <- typeOf f+ n <- getGlobalName f+ MixedAttributeSet fAttrs rAttrs pAttrs <- getMixedAttributeSet f+ parameters <- getParameters f pAttrs+ decodeBlocks <- do+ ffiBasicBlocks <-+ liftIO $ FFI.getXs (FFI.getFirstBasicBlock f) FFI.getNextBasicBlock+ fmap sequence . forM ffiBasicBlocks $ \b -> do+ n <- getLocalName b+ decodeInstructions <- getNamedInstructions b+ decodeTerminator <- getBasicBlockTerminator b+ return $+ A.BasicBlock+ <$> return n+ <*> decodeInstructions+ <*> decodeTerminator+ return $+ A.Function+ <$> getLinkage f+ <*> getVisibility f+ <*> getDLLStorageClass f+ <*> (liftIO $ decodeM =<< FFI.getFunctionCallingConvention f)+ <*> return rAttrs+ <*> return returnType+ <*> return n+ <*> return (parameters, isVarArg)+ <*> return fAttrs+ <*> getSection f+ <*> getCOMDATName f+ <*> getAlignment f+ <*> getGC f+ <*> getPrefixData f+ <*> decodeBlocks+ <*> getPersonalityFn f++decodeNamedMetadataDefinitions :: Ptr FFI.Module -> DecodeAST [A.Definition]+decodeNamedMetadataDefinitions mod = do+ ffiNamedMetadataNodes <-+ liftIO $ FFI.getXs (FFI.getFirstNamedMetadata mod) FFI.getNextNamedMetadata+ forM ffiNamedMetadataNodes $ \nm ->+ scopeAnyCont $ do+ n <- liftIO $ FFI.getNamedMetadataNumOperands nm+ os <- allocaArray n+ liftIO $ FFI.getNamedMetadataOperands nm os+ A.NamedMetadataDefinition+ <$> (decodeM $ FFI.getNamedMetadataName nm)+ <*> fmap+ (map (\(A.MetadataNodeReference mid) -> mid))+ (decodeM (n, os))++-- | Get an LLVM.AST.'LLVM.AST.Module' from a LLVM.'Module' - i.e.+-- raise C++ objects into an Haskell AST.+moduleAST :: Module -> IO A.Module+moduleAST m = runDecodeAST $ do+ mod <- readModule m+ c <- return Context `ap` liftIO (FFI.getModuleContext mod)+ getMetadataKindNames c+ A.Module+ <$> (liftIO $ decodeM =<< FFI.getModuleIdentifier mod)+ <*> (liftIO $ decodeM =<< FFI.getSourceFileName mod)+ <*> (liftIO $ getDataLayout mod)+ <*> (liftIO $ do+ s <- decodeM =<< FFI.getTargetTriple mod+ return $ if s == "" then Nothing else Just s)+ <*> (do+ globalDefinitions <-+ map A.GlobalDefinition . concat <$>+ -- Variables, aliases & functions can reference each other. To+ -- resolve this references properly during decoding a two step+ -- process is used: In the first step, the names of the+ -- different definitions are stored. In the second step we can+ -- then decode the definitions and look up the previously+ -- stored references.+ (join . fmap sequence . sequence)+ [ decodeGlobalVariables mod+ , decodeGlobalAliases mod+ , decodeFunctions mod+ ]+ structDefinitions <- getStructDefinitions+ inlineAsm <- decodeM =<< liftIO (FFI.moduleGetInlineAsm mod)+ namedMetadata <- decodeNamedMetadataDefinitions mod+ metadata <- getMetadataDefinitions+ functionAttributes <- do+ functionAttributes <- gets $ Map.toList . functionAttributeSetIDs+ forM functionAttributes $ \(as, gid) ->+ A.FunctionAttributes <$> return gid <*> decodeM as+ comdats <- gets $ map (uncurry A.COMDAT) . Map.elems . comdats+ return $+ structDefinitions +++ inlineAsm +++ globalDefinitions +++ namedMetadata +++ metadata +++ functionAttributes +++ comdats)
+ src/LLVM/Internal/Operand.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE+ MultiParamTypeClasses+ #-}+module LLVM.Internal.Operand where++import LLVM.Prelude++import Control.Monad.State+import Control.Monad.AnyCont+import qualified Data.Map as Map++import Foreign.Ptr++import qualified LLVM.Internal.FFI.Constant as FFI+import qualified LLVM.Internal.FFI.InlineAssembly as FFI+import qualified LLVM.Internal.FFI.Metadata as FFI+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI+import qualified LLVM.Internal.FFI.Value as FFI++import LLVM.Internal.Coding+import LLVM.Internal.Constant ()+import LLVM.Internal.Context+import LLVM.Internal.DecodeAST+import LLVM.Internal.EncodeAST+import LLVM.Internal.InlineAssembly ()+import LLVM.Internal.Metadata ()++import qualified LLVM.AST as A++instance DecodeM DecodeAST A.Operand (Ptr FFI.Value) where+ decodeM v = do+ c <- liftIO $ FFI.isAConstant v+ if (c /= nullPtr) + then+ return A.ConstantOperand `ap` decodeM c+ else+ do m <- liftIO $ FFI.isAMetadataOperand v+ if (m /= nullPtr)+ then A.MetadataOperand <$> decodeM m+ else return A.LocalReference+ `ap` (decodeM =<< (liftIO $ FFI.typeOf v))+ `ap` getLocalName v++instance DecodeM DecodeAST A.Metadata (Ptr FFI.Metadata) where+ decodeM md = do+ s <- liftIO $ FFI.isAMDString md+ if (s /= nullPtr)+ then A.MDString <$> decodeM s+ else do n <- liftIO $ FFI.isAMDNode md+ if (n /= nullPtr)+ then A.MDNode <$> decodeM n+ else do v <- liftIO $ FFI.isAMDValue md+ if (v /= nullPtr)+ then A.MDValue <$> decodeM v+ else fail "Metadata was not one of [MDString, MDValue, MDNode]"++instance DecodeM DecodeAST A.CallableOperand (Ptr FFI.Value) where+ decodeM v = do+ ia <- liftIO $ FFI.isAInlineAsm v+ if ia /= nullPtr+ then liftM Left (decodeM ia)+ else liftM Right (decodeM v)++instance EncodeM EncodeAST A.Operand (Ptr FFI.Value) where+ encodeM (A.ConstantOperand c) = (FFI.upCast :: Ptr FFI.Constant -> Ptr FFI.Value) <$> encodeM c+ encodeM (A.LocalReference t n) = do+ lv <- refer encodeStateLocals n $ do+ lv <- do+ n <- encodeM n+ t <- encodeM t+ v <- liftIO $ FFI.createArgument t n+ return $ ForwardValue v+ modify $ \s -> s { encodeStateLocals = Map.insert n lv $ encodeStateLocals s }+ return lv+ return $ case lv of DefinedValue v -> v; ForwardValue v -> v+ encodeM (A.MetadataOperand md) = do+ md' <- encodeM md+ Context c <- gets encodeStateContext+ liftIO $ FFI.upCast <$> FFI.metadataOperand c md'++instance EncodeM EncodeAST A.Metadata (Ptr FFI.Metadata) where+ encodeM (A.MDString s) = do+ Context c <- gets encodeStateContext+ s <- encodeM s+ liftM FFI.upCast $ liftIO $ FFI.mdStringInContext c s+ encodeM (A.MDNode mdn) = (FFI.upCast :: Ptr FFI.MDNode -> Ptr FFI.Metadata) <$> encodeM mdn+ encodeM (A.MDValue v) = do+ v <- encodeM v+ liftIO $ FFI.upCast <$> FFI.mdValue v++instance EncodeM EncodeAST A.CallableOperand (Ptr FFI.Value) where+ encodeM (Right o) = encodeM o+ encodeM (Left i) = liftM (FFI.upCast :: Ptr FFI.InlineAsm -> Ptr FFI.Value) (encodeM i)++instance EncodeM EncodeAST A.MetadataNode (Ptr FFI.MDNode) where+ encodeM (A.MetadataNode ops) = scopeAnyCont $ do+ Context c <- gets encodeStateContext+ ops <- encodeM ops+ liftIO $ FFI.createMDNodeInContext c ops+ encodeM (A.MetadataNodeReference n) = referMDNode n++instance DecodeM DecodeAST [Maybe A.Metadata] (Ptr FFI.MDNode) where+ decodeM p = scopeAnyCont $ do+ n <- liftIO $ FFI.getMDNodeNumOperands p+ ops <- allocaArray n+ liftIO $ FFI.getMDNodeOperands p ops+ decodeM (n, ops)++instance DecodeM DecodeAST A.Operand (Ptr FFI.MDValue) where+ decodeM = decodeM <=< liftIO . FFI.getMDValue++instance DecodeM DecodeAST A.Metadata (Ptr FFI.MetadataAsVal) where+ decodeM = decodeM <=< liftIO . FFI.getMetadataOperand++instance DecodeM DecodeAST A.MetadataNode (Ptr FFI.MDNode) where+ decodeM p = scopeAnyCont $ do++ -- fl <- decodeM =<< liftIO (FFI.mdNodeIsFunctionLocal p)+ -- if fl+ -- then+ -- return A.MetadataNode `ap` decodeM p+ -- else+ return A.MetadataNodeReference `ap` getMetadataNodeID p++getMetadataDefinitions :: DecodeAST [A.Definition]+getMetadataDefinitions = fix $ \continue -> do+ mdntd <- takeMetadataNodeToDefine+ flip (maybe (return [])) mdntd $ \(mid, p) -> do+ return (:)+ `ap` (return A.MetadataNodeDefinition `ap` return mid `ap` decodeM p)+ `ap` continue
+ src/LLVM/Internal/OrcJIT.hs view
@@ -0,0 +1,107 @@+{-# LANGUAGE MultiParamTypeClasses #-}+module LLVM.Internal.OrcJIT where++import LLVM.Prelude++import Control.Exception+import Control.Monad.AnyCont+import Control.Monad.IO.Class+import Data.Bits+import Data.ByteString (ByteString, packCString, useAsCString)+import Data.IORef+import Foreign.C.String+import Foreign.Ptr++import LLVM.Internal.Coding+import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import qualified LLVM.Internal.FFI.OrcJIT as FFI++newtype MangledSymbol = MangledSymbol ByteString+ deriving (Show, Eq, Ord)++instance EncodeM (AnyContT IO) MangledSymbol CString where+ encodeM (MangledSymbol bs) = anyContToM $ useAsCString bs++instance MonadIO m => DecodeM m MangledSymbol CString where+ decodeM str = liftIO $ MangledSymbol <$> packCString str++data JITSymbolFlags =+ JITSymbolFlags {+ jitSymbolWeak :: !Bool,+ jitSymbolExported :: !Bool+ }+ deriving (Show, Eq, Ord)++data JITSymbol =+ JITSymbol {+ jitSymbolAddress :: !WordPtr,+ jitSymbolFlags :: !JITSymbolFlags+ }+ deriving (Show, Eq, Ord)++type SymbolResolverFn = MangledSymbol -> IO JITSymbol++data SymbolResolver =+ SymbolResolver {+ dylibResolver :: !SymbolResolverFn,+ externalResolver :: !SymbolResolverFn+ }++newtype ObjectLinkingLayer = ObjectLinkingLayer (Ptr FFI.ObjectLinkingLayer)++instance Monad m => EncodeM m JITSymbolFlags FFI.JITSymbolFlags where+ encodeM f = return $ foldr1 (.|.) [+ if a f+ then b+ else 0+ | (a,b) <- [+ (jitSymbolWeak, FFI.jitSymbolFlagsWeak),+ (jitSymbolExported, FFI.jitSymbolFlagsExported)+ ]+ ]++instance Monad m => DecodeM m JITSymbolFlags FFI.JITSymbolFlags where+ decodeM f =+ return $ JITSymbolFlags {+ jitSymbolWeak = FFI.jitSymbolFlagsWeak .&. f /= 0,+ jitSymbolExported = FFI.jitSymbolFlagsExported .&. f /= 0+ }++instance MonadIO m => EncodeM m JITSymbol (Ptr FFI.JITSymbol -> IO ()) where+ encodeM (JITSymbol addr flags) = return $ \jitSymbol -> do+ flags' <- encodeM flags+ FFI.setJITSymbol jitSymbol (FFI.TargetAddress (fromIntegral addr)) flags'++instance MonadIO m => DecodeM m JITSymbol (Ptr FFI.JITSymbol) where+ decodeM jitSymbol = do+ FFI.TargetAddress addr <- liftIO $ FFI.getAddress jitSymbol+ flags <- liftIO $ decodeM =<< FFI.getFlags jitSymbol+ return (JITSymbol (fromIntegral addr) flags)++instance MonadIO m =>+ EncodeM m SymbolResolver (IORef [IO ()] -> IO (Ptr FFI.LambdaResolver)) where+ encodeM (SymbolResolver dylib external) = return $ \cleanups -> do+ dylib' <- allocFunPtr cleanups (encodeM dylib)+ external' <- allocFunPtr cleanups (encodeM external)+ FFI.createLambdaResolver dylib' external'++instance MonadIO m => EncodeM m SymbolResolverFn (FunPtr FFI.SymbolResolverFn) where+ encodeM callback =+ liftIO $ FFI.wrapSymbolResolverFn+ (\symbol result -> do+ setSymbol <- encodeM =<< callback =<< decodeM symbol+ setSymbol result)++-- | allocate a function pointer and register it for cleanup+allocFunPtr :: IORef [IO ()] -> IO (FunPtr a) -> IO (FunPtr a)+allocFunPtr cleanups alloc = mask $ \restore -> do+ funPtr <- restore alloc+ modifyIORef cleanups (freeHaskellFunPtr funPtr :)+ pure funPtr++withObjectLinkingLayer :: (ObjectLinkingLayer -> IO a) -> IO a+withObjectLinkingLayer f =+ bracket+ FFI.createObjectLinkingLayer+ FFI.disposeObjectLinkingLayer $ \objectLayer ->+ f (ObjectLinkingLayer objectLayer)
+ src/LLVM/Internal/OrcJIT/CompileOnDemandLayer.hs view
@@ -0,0 +1,146 @@+{-# LANGUAGE MultiParamTypeClasses #-}+module LLVM.Internal.OrcJIT.CompileOnDemandLayer where++import LLVM.Prelude++import Control.Exception+import Control.Monad.AnyCont+import Control.Monad.IO.Class+import Data.IORef+import Foreign.Marshal.Array+import Foreign.Ptr++import LLVM.Internal.Coding+import LLVM.Internal.Module+import LLVM.Internal.OrcJIT+import LLVM.Internal.OrcJIT.IRCompileLayer (IRCompileLayer(..))+import qualified LLVM.Internal.OrcJIT.IRCompileLayer as IRCompileLayer+import qualified LLVM.Internal.FFI.OrcJIT as FFI+import qualified LLVM.Internal.FFI.OrcJIT.CompileOnDemandLayer as FFI+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI++type PartitioningFn = Ptr FFI.Function -> IO [Ptr FFI.Function]++newtype JITCompileCallbackManager =+ CallbackMgr (Ptr FFI.JITCompileCallbackManager)++newtype IndirectStubsManagerBuilder =+ StubsMgr (Ptr FFI.IndirectStubsManagerBuilder)++data CompileOnDemandLayer =+ CompileOnDemandLayer {+ compileLayer :: !(Ptr FFI.CompileOnDemandLayer),+ baseLayer :: !IRCompileLayer,+ cleanupActions :: !(IORef [IO ()])+ }+ deriving Eq++newtype ModuleSet = ModuleSet (Ptr FFI.ModuleSetHandle)++instance MonadIO m =>+ EncodeM m PartitioningFn (IORef [IO ()] -> IO (FunPtr FFI.PartitioningFn)) where+ encodeM partition = return $ \cleanups -> do+ allocFunPtr+ cleanups+ (FFI.wrapPartitioningFn+ (\f set -> do+ fs <- partition f+ traverse_ (FFI.insertFun set) fs+ return ()))++instance (MonadIO m, MonadAnyCont IO m) =>+ EncodeM m (Maybe (IO ())) FFI.TargetAddress where+ encodeM Nothing = return $ FFI.TargetAddress 0+ encodeM (Just f) = do+ f' <- anyContToM $ bracket (FFI.wrapErrorHandler f) freeHaskellFunPtr+ return . FFI.TargetAddress . fromIntegral . ptrToWordPtr . castFunPtrToPtr $ f'++withIndirectStubsManagerBuilder ::+ String {- ^ triple -} ->+ (IndirectStubsManagerBuilder -> IO a) ->+ IO a+withIndirectStubsManagerBuilder triple f = flip runAnyContT return $ do+ triple' <- encodeM triple+ stubsMgr <- anyContToM $ bracket+ (FFI.createLocalIndirectStubsManagerBuilder triple')+ FFI.disposeIndirectStubsManagerBuilder+ liftIO $ f (StubsMgr stubsMgr)++withJITCompileCallbackManager ::+ String {- ^ triple -} ->+ Maybe (IO ()) ->+ (JITCompileCallbackManager -> IO a) ->+ IO a+withJITCompileCallbackManager triple errorHandler f = flip runAnyContT return $ do+ triple' <- encodeM triple+ errorHandler' <- encodeM errorHandler+ callbackMgr <- anyContToM $ bracket+ (FFI.createLocalCompileCallbackManager triple' errorHandler')+ FFI.disposeCallbackManager+ liftIO $ f (CallbackMgr callbackMgr)++withCompileOnDemandLayer ::+ IRCompileLayer ->+ PartitioningFn ->+ JITCompileCallbackManager ->+ IndirectStubsManagerBuilder ->+ Bool ->+ (CompileOnDemandLayer -> IO a) ->+ IO a+withCompileOnDemandLayer+ baseLayer@(IRCompileLayer base _ _)+ partition+ (CallbackMgr callbackMgr)+ (StubsMgr stubsMgr)+ cloneStubsIntoPartitions+ f+ = flip runAnyContT return $ do+ cleanup <- anyContToM $ bracket (newIORef []) (sequence <=< readIORef)+ partitionAct <- encodeM partition+ partition' <- liftIO $ partitionAct cleanup+ cloneStubsIntoPartitions' <- encodeM cloneStubsIntoPartitions+ cl <- anyContToM $ bracket+ (FFI.createCompileOnDemandLayer+ base+ partition'+ callbackMgr+ stubsMgr+ cloneStubsIntoPartitions')+ FFI.disposeCompileOnDemandLayer+ liftIO $ f (CompileOnDemandLayer cl baseLayer cleanup)++mangleSymbol :: CompileOnDemandLayer -> String -> IO MangledSymbol+mangleSymbol (CompileOnDemandLayer _ bl _) symbol =+ IRCompileLayer.mangleSymbol bl symbol++findSymbol :: CompileOnDemandLayer -> MangledSymbol -> Bool -> IO JITSymbol+findSymbol (CompileOnDemandLayer cl _ _) symbol exportedSymbolsOnly = flip runAnyContT return $ do+ symbol' <- encodeM symbol+ exportedSymbolsOnly' <- encodeM exportedSymbolsOnly+ symbol <- anyContToM $ bracket+ (FFI.findSymbol cl symbol' exportedSymbolsOnly') FFI.disposeSymbol+ decodeM symbol++addModuleSet :: CompileOnDemandLayer -> [Module] -> SymbolResolver -> IO ModuleSet+addModuleSet+ (CompileOnDemandLayer cl (IRCompileLayer _ dl _) cleanups)+ modules+ resolver+ = flip runAnyContT return $ do+ resolverAct <- encodeM resolver+ resolver' <- liftIO $ resolverAct cleanups+ modules' <- liftIO $ mapM readModule modules+ (moduleCount, modules'') <-+ anyContToM $ \f -> withArrayLen modules' $ \n hs -> f (fromIntegral n, hs)+ moduleSet <- liftIO $ FFI.addModuleSet cl dl modules'' moduleCount resolver'+ pure (ModuleSet moduleSet)++removeModuleSet :: CompileOnDemandLayer -> ModuleSet -> IO ()+removeModuleSet (CompileOnDemandLayer cl _ _) (ModuleSet handle) =+ FFI.removeModuleSet cl handle++withModuleSet :: CompileOnDemandLayer -> [Module] -> SymbolResolver -> (ModuleSet -> IO a) -> IO a+withModuleSet compileLayer modules resolver =+ bracket+ (addModuleSet compileLayer modules resolver)+ (removeModuleSet compileLayer)
+ src/LLVM/Internal/OrcJIT/IRCompileLayer.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE MultiParamTypeClasses #-}+module LLVM.Internal.OrcJIT.IRCompileLayer where++import LLVM.Prelude++import Control.Exception+import Control.Monad.AnyCont+import Control.Monad.IO.Class+import Data.IORef+import Foreign.Marshal.Array (withArrayLen)+import Foreign.Ptr++import LLVM.Internal.Coding+import qualified LLVM.Internal.FFI.DataLayout as FFI+import qualified LLVM.Internal.FFI.OrcJIT as FFI+import qualified LLVM.Internal.FFI.OrcJIT.IRCompileLayer as FFI+import qualified LLVM.Internal.FFI.Target as FFI+import LLVM.Internal.Module+import LLVM.Internal.OrcJIT+import LLVM.Internal.Target++data IRCompileLayer =+ IRCompileLayer {+ compileLayer :: !(Ptr FFI.IRCompileLayer),+ dataLayout :: !(Ptr FFI.DataLayout),+ cleanupActions :: !(IORef [IO ()])+ }+ deriving Eq++newtype ModuleSet = ModuleSet (Ptr FFI.ModuleSetHandle)++withIRCompileLayer :: ObjectLinkingLayer -> TargetMachine -> (IRCompileLayer -> IO a) -> IO a+withIRCompileLayer (ObjectLinkingLayer oll) (TargetMachine tm) f = flip runAnyContT return $ do+ dl <- anyContToM $ bracket (FFI.createTargetDataLayout tm) FFI.disposeDataLayout+ cl <- anyContToM $ bracket (FFI.createIRCompileLayer oll tm) FFI.disposeIRCompileLayer+ cleanup <- anyContToM $ bracket (newIORef []) (sequence <=< readIORef)+ liftIO $ f (IRCompileLayer cl dl cleanup)++mangleSymbol :: IRCompileLayer -> String -> IO MangledSymbol+mangleSymbol (IRCompileLayer _ dl _) symbol = flip runAnyContT return $ do+ mangledSymbol <- alloca+ symbol' <- encodeM symbol+ anyContToM $ bracket+ (FFI.getMangledSymbol mangledSymbol symbol' dl)+ (\_ -> FFI.disposeMangledSymbol =<< peek mangledSymbol)+ decodeM =<< peek mangledSymbol++findSymbol :: IRCompileLayer -> MangledSymbol -> Bool -> IO JITSymbol+findSymbol (IRCompileLayer cl _ _) symbol exportedSymbolsOnly = flip runAnyContT return $ do+ symbol' <- encodeM symbol+ exportedSymbolsOnly' <- encodeM exportedSymbolsOnly+ symbol <- anyContToM $ bracket+ (FFI.findSymbol cl symbol' exportedSymbolsOnly') FFI.disposeSymbol+ decodeM symbol++addModuleSet :: IRCompileLayer -> [Module] -> SymbolResolver -> IO ModuleSet+addModuleSet (IRCompileLayer cl dl cleanups) modules resolver = flip runAnyContT return $ do+ resolverAct <- encodeM resolver+ resolver' <- liftIO $ resolverAct cleanups+ modules' <- liftIO $ mapM readModule modules+ (moduleCount, modules'') <-+ anyContToM $ \f -> withArrayLen modules' $ \n hs -> f (fromIntegral n, hs)+ moduleSet <- liftIO $ FFI.addModuleSet cl dl modules'' moduleCount resolver'+ pure (ModuleSet moduleSet)++removeModuleSet :: IRCompileLayer -> ModuleSet -> IO ()+removeModuleSet (IRCompileLayer cl _ _) (ModuleSet handle) =+ FFI.removeModuleSet cl handle++withModuleSet :: IRCompileLayer -> [Module] -> SymbolResolver -> (ModuleSet -> IO a) -> IO a+withModuleSet compileLayer modules resolver =+ bracket+ (addModuleSet compileLayer modules resolver)+ (removeModuleSet compileLayer)
+ src/LLVM/Internal/PassManager.hs view
@@ -0,0 +1,147 @@+{-# LANGUAGE+ TemplateHaskell,+ MultiParamTypeClasses,+ CPP+ #-}+module LLVM.Internal.PassManager where++import LLVM.Prelude++import qualified Language.Haskell.TH as TH++import Control.Exception+import Control.Monad.IO.Class++import Control.Monad.AnyCont++import Foreign.C (CString)+import Foreign.Ptr++import qualified LLVM.Internal.FFI.PassManager as FFI+import qualified LLVM.Internal.FFI.Transforms as FFI++import LLVM.Internal.Module+import LLVM.Internal.Target+import LLVM.Internal.Coding+import LLVM.Transforms++import LLVM.AST.DataLayout++-- | <http://llvm.org/doxygen/classllvm_1_1PassManager.html>+-- Note: a PassManager does substantive behind-the-scenes work, arranging for the+-- results of various analyses to be available as needed by transform passes, shared+-- as possible.+newtype PassManager = PassManager (Ptr FFI.PassManager)++-- | There are different ways to get a 'PassManager'. This type embodies them.+data PassSetSpec+ -- | a 'PassSetSpec' is a lower-level, detailed specification of a set of passes. It+ -- allows fine-grained control of what passes are to be run when, and the specification+ -- of passes not available through 'CuratedPassSetSpec'.+ = PassSetSpec {+ transforms :: [Pass],+ dataLayout :: Maybe DataLayout,+ targetLibraryInfo :: Maybe TargetLibraryInfo,+ targetMachine :: Maybe TargetMachine+ }+ -- | This type is a high-level specification of a set of passes. It uses the same+ -- collection of passes chosen by the LLVM team in the command line tool 'opt'. The fields+ -- of this spec are much like typical compiler command-line flags - e.g. -O\<n\>, etc.+ | CuratedPassSetSpec {+ optLevel :: Maybe Word,+ sizeLevel :: Maybe Word,+ unitAtATime :: Maybe Bool,+ simplifyLibCalls :: Maybe Bool,+ loopVectorize :: Maybe Bool,+ superwordLevelParallelismVectorize :: Maybe Bool,+ useInlinerWithThreshold :: Maybe Word,+ dataLayout :: Maybe DataLayout,+ targetLibraryInfo :: Maybe TargetLibraryInfo,+ targetMachine :: Maybe TargetMachine+ }++-- | Helper to make a curated 'PassSetSpec'+defaultCuratedPassSetSpec :: PassSetSpec+defaultCuratedPassSetSpec = CuratedPassSetSpec {+ optLevel = Nothing,+ sizeLevel = Nothing,+ unitAtATime = Nothing,+ simplifyLibCalls = Nothing,+ loopVectorize = Nothing,+ superwordLevelParallelismVectorize = Nothing,+ useInlinerWithThreshold = Nothing,+ dataLayout = Nothing,+ targetLibraryInfo = Nothing,+ targetMachine = Nothing+}++-- | an empty 'PassSetSpec'+defaultPassSetSpec :: PassSetSpec+defaultPassSetSpec = PassSetSpec {+ transforms = [],+ dataLayout = Nothing,+ targetLibraryInfo = Nothing,+ targetMachine = Nothing+}++instance (Monad m, MonadAnyCont IO m) => EncodeM m GCOVVersion CString where+ encodeM (GCOVVersion cs@[_,_,_,_]) = encodeM cs++createPassManager :: PassSetSpec -> IO (Ptr FFI.PassManager)+createPassManager pss = flip runAnyContT return $ do+ pm <- liftIO $ FFI.createPassManager+ forM_ (targetLibraryInfo pss) $ \(TargetLibraryInfo tli) -> do+ liftIO $ FFI.addTargetLibraryInfoPass pm tli+ forM_ (targetMachine pss) $ \(TargetMachine tm) -> liftIO $ FFI.addAnalysisPasses tm pm+ case pss of+ s@CuratedPassSetSpec {} -> liftIO $ do+ bracket FFI.passManagerBuilderCreate FFI.passManagerBuilderDispose $ \b -> do+ let handleOption g m = forM_ (m s) (g b <=< encodeM) + handleOption FFI.passManagerBuilderSetOptLevel optLevel+ handleOption FFI.passManagerBuilderSetSizeLevel sizeLevel+ handleOption FFI.passManagerBuilderSetDisableUnitAtATime (liftM not . unitAtATime)+ handleOption FFI.passManagerBuilderSetDisableSimplifyLibCalls (liftM not . simplifyLibCalls)+ handleOption FFI.passManagerBuilderUseInlinerWithThreshold useInlinerWithThreshold+ handleOption FFI.passManagerBuilderSetLoopVectorize loopVectorize+ handleOption FFI.passManagerBuilderSetSuperwordLevelParallelismVectorize superwordLevelParallelismVectorize+ FFI.passManagerBuilderPopulateModulePassManager b pm+ PassSetSpec ps dl tli tm' -> do+ let tm = maybe nullPtr (\(TargetMachine tm) -> tm) tm'+ forM_ ps $ \p -> $(+ do+#if __GLASGOW_HASKELL__ < 800+ TH.TyConI (TH.DataD _ _ _ cons _) <- TH.reify ''Pass+#else+ TH.TyConI (TH.DataD _ _ _ _ cons _) <- TH.reify ''Pass+#endif+ TH.caseE [| p |] $ flip map cons $ \con -> do+ let+ (n, fns) = case con of+ TH.RecC n fs -> (n, [ TH.nameBase fn | (fn, _, _) <- fs ])+ TH.NormalC n [] -> (n, [])+ actions = + [ TH.bindS (TH.varP . TH.mkName $ fn) [| encodeM $(TH.dyn fn) |] | fn <- fns ]+ ++ [+ TH.noBindS [|+ liftIO $(+ foldl1 TH.appE+ (map TH.dyn $+ ["FFI.add" ++ TH.nameBase n ++ "Pass", "pm"]+ ++ ["tm" | FFI.needsTargetMachine (TH.nameBase n)]+ ++ fns)+ )+ |]+ ]+ TH.match (TH.conP n $ map (TH.varP . TH.mkName) fns) (TH.normalB (TH.doE actions)) []+ )+ return pm++-- | bracket the creation of a 'PassManager'+withPassManager :: PassSetSpec -> (PassManager -> IO a) -> IO a+withPassManager s = bracket (createPassManager s) FFI.disposePassManager . (. PassManager)++-- | run the passes in a 'PassManager' on a 'Module', modifying the 'Module'.+runPassManager :: PassManager -> Module -> IO Bool+runPassManager (PassManager p) m = do+ m' <- readModule m+ toEnum . fromIntegral <$> FFI.runPassManager p m'
+ src/LLVM/Internal/RMWOperation.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE+ TemplateHaskell,+ MultiParamTypeClasses+ #-}+module LLVM.Internal.RMWOperation where++import LLVM.AST.RMWOperation++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI++import LLVM.Internal.Coding++genCodingInstance [t| RMWOperation |] ''FFI.RMWOperation [+ (FFI.rmwOperationXchg, Xchg),+ (FFI.rmwOperationAdd, Add),+ (FFI.rmwOperationSub, Sub),+ (FFI.rmwOperationAnd, And),+ (FFI.rmwOperationNand, Nand),+ (FFI.rmwOperationOr, Or),+ (FFI.rmwOperationXor, Xor),+ (FFI.rmwOperationMax, Max),+ (FFI.rmwOperationMin, Min),+ (FFI.rmwOperationUMax, UMax),+ (FFI.rmwOperationUMin, UMin)+ ]
+ src/LLVM/Internal/RawOStream.hs view
@@ -0,0 +1,79 @@+module LLVM.Internal.RawOStream where++import LLVM.Prelude++import Control.Monad.AnyCont+import Control.Monad.Error.Class+import Control.Monad.IO.Class+import Control.Monad.Trans.Except++import Data.IORef+import Foreign.C+import Foreign.Ptr++import qualified LLVM.Internal.FFI.RawOStream as FFI+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI++import LLVM.Internal.Coding+import LLVM.Internal.Inject+import LLVM.Internal.String ()++withFileRawOStream ::+ (Inject String e, MonadError e m, MonadAnyCont IO m, MonadIO m)+ => String+ -> Bool+ -> Bool+ -> (Ptr FFI.RawOStream -> ExceptT String IO ())+ -> m ()+withFileRawOStream path excl text c =+ withFileRawPWriteStream path excl text (c . FFI.upCast)++withFileRawPWriteStream ::+ (Inject String e, MonadError e m, MonadAnyCont IO m, MonadIO m)+ => String+ -> Bool+ -> Bool+ -> (Ptr FFI.RawPWriteStream -> ExceptT String IO ())+ -> m ()+withFileRawPWriteStream path excl text c = do+ path <- encodeM path+ excl <- encodeM excl+ text <- encodeM text+ msgPtr <- alloca+ errorRef <- liftIO $ newIORef undefined+ succeeded <- decodeM =<< (liftIO $ FFI.withFileRawPWriteStream path excl text msgPtr $ \os -> do+ r <- runExceptT (c os)+ writeIORef errorRef r)+ unless succeeded $ do+ s <- decodeM msgPtr+ throwError $ inject (s :: String)+ e <- liftIO $ readIORef errorRef+ either (throwError . inject) return e++withBufferRawOStream ::+ (Inject String e, MonadError e m, MonadIO m, DecodeM IO a (Ptr CChar, CSize))+ => (Ptr FFI.RawOStream -> ExceptT String IO ())+ -> m a+withBufferRawOStream c = withBufferRawPWriteStream (c . FFI.upCast)++withBufferRawPWriteStream ::+ (Inject String e, MonadError e m, MonadIO m, DecodeM IO a (Ptr CChar, CSize))+ => (Ptr FFI.RawPWriteStream -> ExceptT String IO ())+ -> m a+withBufferRawPWriteStream c = do+ resultRef <- liftIO $ newIORef Nothing+ errorRef <- liftIO $ newIORef undefined+ let saveBuffer :: Ptr CChar -> CSize -> IO ()+ saveBuffer start size = do+ r <- decodeM (start, size)+ writeIORef resultRef (Just r)+ saveError os = do+ r <- runExceptT (c os)+ writeIORef errorRef r+ liftIO $ FFI.withBufferRawPWriteStream saveBuffer saveError+ e <- liftIO $ readIORef errorRef+ case e of+ Left e -> throwError $ inject e+ _ -> do+ Just r <- liftIO $ readIORef resultRef+ return r
+ src/LLVM/Internal/String.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE+ MultiParamTypeClasses,+ UndecidableInstances+ #-}+module LLVM.Internal.String where++import LLVM.Prelude++import Control.Arrow+import Control.Monad.AnyCont+import Control.Monad.IO.Class+import Control.Exception (finally)+import Data.Maybe (fromMaybe)+import Foreign.C (CString, CChar)+import Foreign.Ptr+import Foreign.Storable (Storable)+import Foreign.Marshal.Alloc as F.M (alloca, free)++import LLVM.Internal.FFI.LLVMCTypes++import LLVM.Internal.Coding++import qualified Data.ByteString as BS+import qualified Data.ByteString.Unsafe as BS+import qualified Data.ByteString.UTF8 as BSUTF8++newtype UTF8ByteString = UTF8ByteString { utf8Bytes :: BS.ByteString }++instance (Monad e) => EncodeM e String UTF8ByteString where+ encodeM = return . UTF8ByteString . BSUTF8.fromString++instance (Monad d) => DecodeM d String UTF8ByteString where+ decodeM = return . BSUTF8.toString . utf8Bytes++instance (MonadAnyCont IO e) => EncodeM e String CString where+ encodeM s = anyContToM (BS.unsafeUseAsCString . utf8Bytes =<< encodeM (s ++ "\0"))++instance (Integral i, MonadAnyCont IO e) => EncodeM e String (Ptr CChar, i) where+ encodeM s = anyContToM ((. (. second fromIntegral)) $ BS.useAsCStringLen . utf8Bytes =<< encodeM s)++instance (MonadIO d) => DecodeM d String CString where+ decodeM = decodeM . UTF8ByteString <=< liftIO . BS.packCString++instance (MonadIO d) => DecodeM d String (OwnerTransfered CString) where+ decodeM (OwnerTransfered s) = liftIO $ finally (decodeM s) (free s)++instance (MonadIO d) => DecodeM d String (Ptr (OwnerTransfered CString)) where+ decodeM = liftIO . decodeM <=< peek++instance (Integral i, MonadIO d) => DecodeM d String (Ptr CChar, i) where+ decodeM = decodeM . UTF8ByteString <=< liftIO . BS.packCStringLen . second fromIntegral++instance (Integral i, MonadIO d) => DecodeM d BS.ByteString (Ptr CChar, i) where+ decodeM = liftIO . BS.packCStringLen . second fromIntegral++instance (Integral i, Storable i, MonadIO d) => DecodeM d String (Ptr i -> IO (Ptr CChar)) where+ decodeM f = decodeM =<< (liftIO $ F.M.alloca $ \p -> (,) `liftM` f p `ap` peek p)++instance (Monad e, EncodeM e String c) => EncodeM e (Maybe String) (NothingAsEmptyString c) where+ encodeM = liftM NothingAsEmptyString . encodeM . fromMaybe ""+
+ src/LLVM/Internal/TailCallKind.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE+ TemplateHaskell,+ MultiParamTypeClasses+ #-}+module LLVM.Internal.TailCallKind where++import LLVM.Prelude++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI++import LLVM.Internal.Coding+import qualified LLVM.AST as A++genCodingInstance [t| Maybe A.TailCallKind |] ''FFI.TailCallKind [+ (FFI.tailCallKindNone, Nothing),+ (FFI.tailCallKindTail, Just A.Tail),+ (FFI.tailCallKindMustTail, Just A.MustTail)+ ]
+ src/LLVM/Internal/Target.hs view
@@ -0,0 +1,314 @@+{-# LANGUAGE+ TemplateHaskell,+ MultiParamTypeClasses,+ RecordWildCards,+ UndecidableInstances+ #-}+module LLVM.Internal.Target where++import LLVM.Prelude++import Control.Exception+import Control.Monad.AnyCont+import Control.Monad.Error.Class+import Control.Monad.IO.Class+import Control.Monad.Trans.Except++import Foreign.Ptr+import Foreign.C.String+import Data.List (intercalate)+import Data.Map (Map)+import qualified Data.Map as Map++import Text.ParserCombinators.Parsec hiding (many)++import LLVM.Internal.Coding+import LLVM.Internal.String ()+import LLVM.Internal.LibraryFunction+import LLVM.DataLayout++import LLVM.AST.DataLayout++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import qualified LLVM.Internal.FFI.Target as FFI++import qualified LLVM.Relocation as Reloc+import qualified LLVM.Target.Options as TO+import qualified LLVM.CodeModel as CodeModel+import qualified LLVM.CodeGenOpt as CodeGenOpt++genCodingInstance [t| Reloc.Model |] ''FFI.RelocModel [+ (FFI.relocModelDefault, Reloc.Default),+ (FFI.relocModelStatic, Reloc.Static),+ (FFI.relocModelPIC, Reloc.PIC),+ (FFI.relocModelDynamicNoPic, Reloc.DynamicNoPIC)+ ]++genCodingInstance [t| CodeModel.Model |] ''FFI.CodeModel [+ (FFI.codeModelDefault,CodeModel.Default),+ (FFI.codeModelJITDefault, CodeModel.JITDefault),+ (FFI.codeModelSmall, CodeModel.Small),+ (FFI.codeModelKernel, CodeModel.Kernel),+ (FFI.codeModelMedium, CodeModel.Medium),+ (FFI.codeModelLarge, CodeModel.Large)+ ]++genCodingInstance [t| CodeGenOpt.Level |] ''FFI.CodeGenOptLevel [+ (FFI.codeGenOptLevelNone, CodeGenOpt.None),+ (FFI.codeGenOptLevelLess, CodeGenOpt.Less),+ (FFI.codeGenOptLevelDefault, CodeGenOpt.Default),+ (FFI.codeGenOptLevelAggressive, CodeGenOpt.Aggressive)+ ]++genCodingInstance [t| TO.FloatABI |] ''FFI.FloatABIType [+ (FFI.floatABIDefault, TO.FloatABIDefault),+ (FFI.floatABISoft, TO.FloatABISoft),+ (FFI.floatABIHard, TO.FloatABIHard)+ ]++genCodingInstance [t| TO.FloatingPointOperationFusionMode |] ''FFI.FPOpFusionMode [+ (FFI.fpOpFusionModeFast, TO.FloatingPointOperationFusionFast),+ (FFI.fpOpFusionModeStandard, TO.FloatingPointOperationFusionStandard),+ (FFI.fpOpFusionModeStrict, TO.FloatingPointOperationFusionStrict)+ ]++-- | <http://llvm.org/doxygen/classllvm_1_1Target.html>+newtype Target = Target (Ptr FFI.Target)++-- | e.g. an instruction set extension+newtype CPUFeature = CPUFeature String+ deriving (Eq, Ord, Read, Show)++instance EncodeM e String es => EncodeM e (Map CPUFeature Bool) es where+ encodeM = encodeM . intercalate "," . map (\(CPUFeature f, enabled) -> (if enabled then "+" else "-") ++ f) . Map.toList++instance (Monad d, DecodeM d String es) => DecodeM d (Map CPUFeature Bool) es where+ decodeM es = do+ s <- decodeM es+ let flag = do+ en <- choice [char '-' >> return False, char '+' >> return True]+ s <- many1 (noneOf ",")+ return (CPUFeature s, en)+ features = liftM Map.fromList (flag `sepBy` (char ','))+ case parse (do f <- features; eof; return f) "CPU Feature string" (s :: String) of+ Right features -> return features+ Left _ -> fail "failure to parse CPUFeature string"+ +-- | Find a 'Target' given an architecture and/or a \"triple\".+-- | <http://llvm.org/doxygen/structllvm_1_1TargetRegistry.html#a3105b45e546c9cc3cf78d0f2ec18ad89>+-- | Be sure to run either 'initializeAllTargets' or 'initializeNativeTarget' before expecting this to succeed, depending on what target(s) you want to use.+lookupTarget ::+ Maybe String -- ^ arch+ -> String -- ^ \"triple\" - e.g. x86_64-unknown-linux-gnu+ -> ExceptT String IO (Target, String)+lookupTarget arch triple = flip runAnyContT return $ do+ cErrorP <- alloca+ cNewTripleP <- alloca+ arch <- encodeM (maybe "" id arch)+ triple <- encodeM triple+ target <- liftIO $ FFI.lookupTarget arch triple cNewTripleP cErrorP+ when (target == nullPtr) $ throwError =<< decodeM cErrorP+ liftM (Target target, ) $ decodeM cNewTripleP++-- | <http://llvm.org/doxygen/classllvm_1_1TargetOptions.html>+newtype TargetOptions = TargetOptions (Ptr FFI.TargetOptions)++-- | bracket creation and destruction of a 'TargetOptions' object+withTargetOptions :: (TargetOptions -> IO a) -> IO a+withTargetOptions = bracket FFI.createTargetOptions FFI.disposeTargetOptions . (. TargetOptions)++-- | set all target options+pokeTargetOptions :: TO.Options -> TargetOptions -> IO ()+pokeTargetOptions hOpts (TargetOptions cOpts) = do+ mapM_ (\(c, ha) -> FFI.setTargetOptionFlag cOpts c =<< encodeM (ha hOpts)) [+ (FFI.targetOptionFlagPrintMachineCode, TO.printMachineCode),+ (FFI.targetOptionFlagLessPreciseFPMADOption, TO.lessPreciseFloatingPointMultiplyAddOption),+ (FFI.targetOptionFlagUnsafeFPMath, TO.unsafeFloatingPointMath),+ (FFI.targetOptionFlagNoInfsFPMath, TO.noInfinitiesFloatingPointMath),+ (FFI.targetOptionFlagNoNaNsFPMath, TO.noNaNsFloatingPointMath),+ (FFI.targetOptionFlagHonorSignDependentRoundingFPMathOption, TO.honorSignDependentRoundingFloatingPointMathOption),+ (FFI.targetOptionFlagNoZerosInBSS, TO.noZerosInBSS),+ (FFI.targetOptionFlagGuaranteedTailCallOpt, TO.guaranteedTailCallOptimization),+ (FFI.targetOptionFlagEnableFastISel, TO.enableFastInstructionSelection),+ (FFI.targetOptionFlagUseInitArray, TO.useInitArray),+ (FFI.targetOptionFlagDisableIntegratedAS, TO.disableIntegratedAssembler),+ (FFI.targetOptionFlagCompressDebugSections, TO.compressDebugSections),+ (FFI.targetOptionFlagTrapUnreachable, TO.trapUnreachable)+ ]+ FFI.setStackAlignmentOverride cOpts =<< encodeM (TO.stackAlignmentOverride hOpts)+ FFI.setFloatABIType cOpts =<< encodeM (TO.floatABIType hOpts)+ FFI.setAllowFPOpFusion cOpts =<< encodeM (TO.allowFloatingPointOperationFusion hOpts)++-- | get all target options+peekTargetOptions :: TargetOptions -> IO TO.Options+peekTargetOptions (TargetOptions tOpts) = do+ let gof = decodeM <=< FFI.getTargetOptionsFlag tOpts+ printMachineCode+ <- gof FFI.targetOptionFlagPrintMachineCode+ lessPreciseFloatingPointMultiplyAddOption+ <- gof FFI.targetOptionFlagLessPreciseFPMADOption+ unsafeFloatingPointMath+ <- gof FFI.targetOptionFlagUnsafeFPMath+ noInfinitiesFloatingPointMath+ <- gof FFI.targetOptionFlagNoInfsFPMath+ noNaNsFloatingPointMath+ <- gof FFI.targetOptionFlagNoNaNsFPMath+ honorSignDependentRoundingFloatingPointMathOption+ <- gof FFI.targetOptionFlagHonorSignDependentRoundingFPMathOption+ noZerosInBSS+ <- gof FFI.targetOptionFlagNoZerosInBSS+ guaranteedTailCallOptimization+ <- gof FFI.targetOptionFlagGuaranteedTailCallOpt+ enableFastInstructionSelection+ <- gof FFI.targetOptionFlagEnableFastISel+ useInitArray+ <- gof FFI.targetOptionFlagUseInitArray+ disableIntegratedAssembler+ <- gof FFI.targetOptionFlagDisableIntegratedAS+ compressDebugSections+ <- gof FFI.targetOptionFlagCompressDebugSections+ trapUnreachable+ <- gof FFI.targetOptionFlagTrapUnreachable+ stackAlignmentOverride <- decodeM =<< FFI.getStackAlignmentOverride tOpts+ floatABIType <- decodeM =<< FFI.getFloatABIType tOpts+ allowFloatingPointOperationFusion <- decodeM =<< FFI.getAllowFPOpFusion tOpts+ return TO.Options { .. }++-- | <http://llvm.org/doxygen/classllvm_1_1TargetMachine.html>+newtype TargetMachine = TargetMachine (Ptr FFI.TargetMachine)++-- | bracket creation and destruction of a 'TargetMachine'+withTargetMachine ::+ Target+ -> String -- ^ triple+ -> String -- ^ cpu+ -> Map CPUFeature Bool -- ^ features+ -> TargetOptions+ -> Reloc.Model+ -> CodeModel.Model+ -> CodeGenOpt.Level+ -> (TargetMachine -> IO a)+ -> IO a+withTargetMachine+ (Target target)+ triple+ cpu+ features+ (TargetOptions targetOptions)+ relocModel+ codeModel+ codeGenOptLevel = runAnyContT $ do+ triple <- encodeM triple+ cpu <- encodeM cpu+ features <- encodeM features+ relocModel <- encodeM relocModel+ codeModel <- encodeM codeModel+ codeGenOptLevel <- encodeM codeGenOptLevel+ anyContToM $ bracket (+ FFI.createTargetMachine+ target+ triple+ cpu+ features+ targetOptions+ relocModel+ codeModel+ codeGenOptLevel+ )+ FFI.disposeTargetMachine+ . (. TargetMachine)++-- | <http://llvm.org/doxygen/classllvm_1_1TargetLowering.html>+newtype TargetLowering = TargetLowering (Ptr FFI.TargetLowering)++-- | get the 'TargetLowering' of a 'TargetMachine'+getTargetLowering :: TargetMachine -> IO TargetLowering+getTargetLowering (TargetMachine tm) = TargetLowering <$> error "FIXME: getTargetLowering" -- FFI.getTargetLowering tm++-- | Initialize the native target. This function is called automatically in these Haskell bindings+-- when creating an 'LLVM.ExecutionEngine.ExecutionEngine' which will require it, and so it should+-- not be necessary to call it separately.+initializeNativeTarget :: IO ()+initializeNativeTarget = do+ failure <- decodeM =<< liftIO FFI.initializeNativeTarget+ when failure $ fail "native target initialization failed"++-- | the target triple corresponding to the target machine+getTargetMachineTriple :: TargetMachine -> IO String+getTargetMachineTriple (TargetMachine m) = decodeM =<< FFI.getTargetMachineTriple m++-- | the default target triple that LLVM has been configured to produce code for+getDefaultTargetTriple :: IO String+getDefaultTargetTriple = decodeM =<< FFI.getDefaultTargetTriple++-- | a target triple suitable for loading code into the current process+getProcessTargetTriple :: IO String+getProcessTargetTriple = decodeM =<< FFI.getProcessTargetTriple++-- | the LLVM name for the host CPU+getHostCPUName :: IO String+getHostCPUName = decodeM FFI.getHostCPUName++-- | a space-separated list of LLVM feature names supported by the host CPU+getHostCPUFeatures :: IO (Map CPUFeature Bool)+getHostCPUFeatures =+ decodeM =<< FFI.getHostCPUFeatures++-- | 'DataLayout' to use for the given 'TargetMachine'+getTargetMachineDataLayout :: TargetMachine -> IO DataLayout+getTargetMachineDataLayout (TargetMachine m) = do+ dlString <- decodeM =<< FFI.getTargetMachineDataLayout m+ let Right (Just dl) = runExcept . parseDataLayout BigEndian $ dlString+ return dl++-- | Initialize all targets so they can be found by 'lookupTarget'+initializeAllTargets :: IO ()+initializeAllTargets = FFI.initializeAllTargets++-- | Bracket creation and destruction of a 'TargetMachine' configured for the host+withHostTargetMachine :: (TargetMachine -> IO a) -> ExceptT String IO a+withHostTargetMachine f = do+ liftIO $ initializeAllTargets+ triple <- liftIO $ getProcessTargetTriple+ cpu <- liftIO $ getHostCPUName+ features <- liftIO $ getHostCPUFeatures+ (target, _) <- lookupTarget Nothing triple+ liftIO $ withTargetOptions $ \options ->+ withTargetMachine target triple cpu features options Reloc.Default CodeModel.Default CodeGenOpt.Default f++-- | <http://llvm.org/docs/doxygen/html/classllvm_1_1TargetLibraryInfo.html>+newtype TargetLibraryInfo = TargetLibraryInfo (Ptr FFI.TargetLibraryInfo)++-- | Look up a 'LibraryFunction' by its standard name+getLibraryFunction :: TargetLibraryInfo -> String -> IO (Maybe LibraryFunction)+getLibraryFunction (TargetLibraryInfo f) name = flip runAnyContT return $ do+ libFuncP <- alloca :: AnyContT IO (Ptr FFI.LibFunc)+ name <- (encodeM name :: AnyContT IO CString)+ r <- decodeM =<< (liftIO $ FFI.getLibFunc f name libFuncP)+ forM (if r then Just libFuncP else Nothing) $ decodeM <=< peek++-- | Get a the current name to be emitted for a 'LibraryFunction'+getLibraryFunctionName :: TargetLibraryInfo -> LibraryFunction -> IO String+getLibraryFunctionName (TargetLibraryInfo f) l = flip runAnyContT return $ do+ l <- encodeM l+ decodeM $ FFI.libFuncGetName f l++-- | Set the name of the function on the target platform that corresponds to funcName+setLibraryFunctionAvailableWithName ::+ TargetLibraryInfo+ -> LibraryFunction+ -> String -- ^ The function name to be emitted+ -> IO ()+setLibraryFunctionAvailableWithName (TargetLibraryInfo f) libraryFunction name = flip runAnyContT return $ do+ name <- encodeM name+ libraryFunction <- encodeM libraryFunction+ liftIO $ FFI.libFuncSetAvailableWithName f libraryFunction name++-- | look up information about the library functions available on a given platform+withTargetLibraryInfo ::+ String -- ^ triple+ -> (TargetLibraryInfo -> IO a)+ -> IO a+withTargetLibraryInfo triple f = flip runAnyContT return $ do+ triple <- encodeM triple+ liftIO $ bracket (FFI.createTargetLibraryInfo triple) FFI.disposeTargetLibraryInfo (f . TargetLibraryInfo)
+ src/LLVM/Internal/Threading.hs view
@@ -0,0 +1,13 @@+module LLVM.Internal.Threading (+ isMultithreaded+ ) where++import LLVM.Prelude++import qualified LLVM.Internal.FFI.Threading as FFI++import LLVM.Internal.Coding++-- | Check if multithreading is enabled in LLVM+isMultithreaded :: IO Bool+isMultithreaded = FFI.isMultithreaded >>= decodeM
+ src/LLVM/Internal/Type.hs view
@@ -0,0 +1,164 @@+{-# LANGUAGE+ QuasiQuotes,+ MultiParamTypeClasses+ #-}+module LLVM.Internal.Type where++import LLVM.Prelude++import Control.Monad.AnyCont+import Control.Monad.Error.Class+import Control.Monad.State++import qualified Data.Set as Set++import Foreign.Ptr++import qualified LLVM.Internal.FFI.LLVMCTypes as FFI+import LLVM.Internal.FFI.LLVMCTypes (typeKindP)+import qualified LLVM.Internal.FFI.Type as FFI+import qualified LLVM.Internal.FFI.PtrHierarchy as FFI++import qualified LLVM.AST as A+import qualified LLVM.AST.AddrSpace as A++import LLVM.Internal.Context+import LLVM.Internal.Coding+import LLVM.Internal.DecodeAST+import LLVM.Internal.EncodeAST++getStructure :: Ptr FFI.Type -> DecodeAST A.Type+getStructure t = scopeAnyCont $ do+ return A.StructureType+ `ap` (decodeM =<< liftIO (FFI.isPackedStruct t))+ `ap` do+ n <- liftIO (FFI.countStructElementTypes t)+ ts <- allocaArray n+ liftIO $ FFI.getStructElementTypes t ts+ decodeM (n, ts)++getStructDefinitions :: DecodeAST [A.Definition]+getStructDefinitions = do+ let getStructDefinition t = do+ opaque <- decodeM =<< liftIO (FFI.structIsOpaque t)+ if opaque then return Nothing else Just <$> getStructure t+ flip fix Set.empty $ \continue done -> do+ t <- takeTypeToDefine+ flip (maybe (return [])) t $ \t -> do+ if t `Set.member` done+ then+ continue done+ else+ return (:)+ `ap` (return A.TypeDefinition `ap` getTypeName t `ap` getStructDefinition t)+ `ap` (continue $ Set.insert t done)++isArrayType :: Ptr FFI.Type -> IO Bool+isArrayType t = do+ k <- liftIO $ FFI.getTypeKind t+ return $ k == FFI.typeKindArray++instance Monad m => EncodeM m A.AddrSpace FFI.AddrSpace where+ encodeM (A.AddrSpace a) = return FFI.AddrSpace `ap` encodeM a++instance Monad m => DecodeM m A.AddrSpace FFI.AddrSpace where+ decodeM (FFI.AddrSpace a) = return A.AddrSpace `ap` decodeM a++instance EncodeM EncodeAST A.Type (Ptr FFI.Type) where+ encodeM f = scopeAnyCont $ do+ Context context <- gets encodeStateContext+ case f of+ A.IntegerType bits -> do+ bits <- encodeM bits+ liftIO $ FFI.intTypeInContext context bits+ A.FunctionType returnTypeAST argTypeASTs isVarArg -> do+ returnType <- encodeM returnTypeAST+ argTypes <- encodeM argTypeASTs+ isVarArg <- encodeM isVarArg+ liftIO $ FFI.functionType returnType argTypes isVarArg+ A.PointerType elementType addressSpace -> do+ e <- encodeM elementType+ a <- encodeM addressSpace+ liftIO $ FFI.pointerType e a+ A.VoidType -> liftIO $ FFI.voidTypeInContext context+ A.FloatingPointType 16 A.IEEE -> liftIO $ FFI.halfTypeInContext context+ A.FloatingPointType 32 A.IEEE -> liftIO $ FFI.floatTypeInContext context+ A.FloatingPointType 64 A.IEEE -> liftIO $ FFI.doubleTypeInContext context+ A.FloatingPointType 80 A.DoubleExtended -> liftIO $ FFI.x86FP80TypeInContext context+ A.FloatingPointType 128 A.IEEE -> liftIO $ FFI.fP128TypeInContext context+ A.FloatingPointType 128 A.PairOfFloats -> liftIO $ FFI.ppcFP128TypeInContext context+ A.FloatingPointType _ _ -> throwError $ "unsupported floating point type: " ++ show f+ A.VectorType sz e -> do+ e <- encodeM e+ sz <- encodeM sz+ liftIO $ FFI.vectorType e sz+ A.ArrayType sz e -> do+ e <- encodeM e+ sz <- encodeM sz+ liftIO $ FFI.arrayType e sz+ A.StructureType packed ets -> do+ ets <- encodeM ets+ packed <- encodeM packed+ liftIO $ FFI.structTypeInContext context ets packed+ A.NamedTypeReference n -> lookupNamedType n+ A.MetadataType -> liftIO $ FFI.metadataTypeInContext context+ A.TokenType -> liftIO $ FFI.tokenTypeInContext context++instance DecodeM DecodeAST A.Type (Ptr FFI.Type) where+ decodeM t = scopeAnyCont $ do+ k <- liftIO $ FFI.getTypeKind t+ case k of+ [typeKindP|Void|] -> return A.VoidType+ [typeKindP|Integer|] -> A.IntegerType <$> (decodeM =<< liftIO (FFI.getIntTypeWidth t))+ [typeKindP|Function|] ->+ return A.FunctionType+ `ap` (decodeM =<< liftIO (FFI.getReturnType t))+ `ap` (do+ n <- liftIO (FFI.countParamTypes t)+ ts <- allocaArray n+ liftIO $ FFI.getParamTypes t ts+ decodeM (n, ts)+ )+ `ap` (decodeM =<< liftIO (FFI.isFunctionVarArg t))+ [typeKindP|Pointer|] ->+ return A.PointerType+ `ap` (decodeM =<< liftIO (FFI.getElementType t))+ `ap` (decodeM =<< liftIO (FFI.getPointerAddressSpace t))+ [typeKindP|Half|] -> return $ A.FloatingPointType 16 A.IEEE+ [typeKindP|Float|] -> return $ A.FloatingPointType 32 A.IEEE+ [typeKindP|Double|] -> return $ A.FloatingPointType 64 A.IEEE+ [typeKindP|FP128|] -> return $ A.FloatingPointType 128 A.IEEE+ [typeKindP|X86_FP80|] -> return $ A.FloatingPointType 80 A.DoubleExtended+ [typeKindP|PPC_FP128|] -> return $ A.FloatingPointType 128 A.PairOfFloats+ [typeKindP|Vector|] ->+ return A.VectorType+ `ap` (decodeM =<< liftIO (FFI.getVectorSize t))+ `ap` (decodeM =<< liftIO (FFI.getElementType t))+ [typeKindP|Struct|] -> do+ let ifM c a b = c >>= \x -> if x then a else b+ ifM (decodeM =<< liftIO (FFI.structIsLiteral t))+ (getStructure t)+ (saveNamedType t >> return A.NamedTypeReference `ap` getTypeName t)+ [typeKindP|Metadata|] -> return A.MetadataType+ [typeKindP|Array|] ->+ return A.ArrayType+ `ap` (decodeM =<< liftIO (FFI.getArrayLength t))+ `ap` (decodeM =<< liftIO (FFI.getElementType t))+ [typeKindP|Token|] -> return A.TokenType+ _ -> error $ "unhandled type kind " ++ show k++createNamedType :: A.Name -> EncodeAST (Ptr FFI.Type)+createNamedType n = do+ Context c <- gets encodeStateContext+ n <- case n of { A.Name n -> encodeM n; _ -> return nullPtr }+ liftIO $ FFI.structCreateNamed c n+++setNamedType :: Ptr FFI.Type -> A.Type -> EncodeAST ()+setNamedType t (A.StructureType packed ets) = do+ ets <- encodeM ets+ packed <- encodeM packed+ liftIO $ FFI.structSetBody t ets packed+++
+ src/LLVM/Internal/Value.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE+ MultiParamTypeClasses+ #-}+module LLVM.Internal.Value where++import LLVM.Prelude++import Control.Monad.State++import Foreign.Ptr++import qualified LLVM.Internal.FFI.PtrHierarchy as FFI+import qualified LLVM.Internal.FFI.Value as FFI++import LLVM.Internal.Coding+import LLVM.Internal.DecodeAST+import LLVM.Internal.Type () +import LLVM.Internal.Constant () ++import qualified LLVM.AST.Type as A++typeOf :: FFI.DescendentOf FFI.Value v => Ptr v -> DecodeAST A.Type+typeOf = decodeM <=< liftIO . FFI.typeOf . FFI.upCast+
+ src/LLVM/Module.hs view
@@ -0,0 +1,27 @@+-- | A 'Module' holds a C++ LLVM IR module. 'Module's may be converted to or from strings or Haskell ASTs, or+-- added to an 'LLVM.ExecutionEngine.ExecutionEngine' and so JIT compiled to get function pointers.+module LLVM.Module (+ Module,+ File(..),++ withModuleFromAST,+ moduleAST,++ withModuleFromLLVMAssembly,+ moduleLLVMAssembly,+ writeLLVMAssemblyToFile,++ withModuleFromBitcode,+ moduleBitcode,+ writeBitcodeToFile,++ moduleTargetAssembly,+ writeTargetAssemblyToFile,++ moduleObject,+ writeObjectToFile,++ linkModules+ ) where++import LLVM.Internal.Module
+ src/LLVM/OrcJIT.hs view
@@ -0,0 +1,11 @@+module LLVM.OrcJIT (+ JITSymbol(..),+ JITSymbolFlags(..),+ MangledSymbol,+ ObjectLinkingLayer,+ SymbolResolver(..),+ SymbolResolverFn,+ withObjectLinkingLayer+ ) where++import LLVM.Internal.OrcJIT
+ src/LLVM/OrcJIT/CompileOnDemandLayer.hs view
@@ -0,0 +1,14 @@+module LLVM.OrcJIT.CompileOnDemandLayer (+ PartitioningFn,+ JITCompileCallbackManager,+ IndirectStubsManagerBuilder,+ CompileOnDemandLayer,+ withIndirectStubsManagerBuilder,+ withJITCompileCallbackManager,+ withCompileOnDemandLayer,+ mangleSymbol,+ findSymbol,+ withModuleSet+ ) where++import LLVM.Internal.OrcJIT.CompileOnDemandLayer
+ src/LLVM/OrcJIT/IRCompileLayer.hs view
@@ -0,0 +1,10 @@+module LLVM.OrcJIT.IRCompileLayer (+ IRCompileLayer,+ ModuleSet,+ findSymbol,+ mangleSymbol,+ withIRCompileLayer,+ withModuleSet+ ) where++import LLVM.Internal.OrcJIT.IRCompileLayer
+ src/LLVM/PassManager.hs view
@@ -0,0 +1,14 @@+-- | A 'PassManager' holds collection of passes, to be run on 'Module's.+-- Build one with 'withPassManager':+-- +-- * using 'CuratedPassSetSpec' if you want optimization but not to play with your compiler+--+-- * using 'PassSetSpec' if you do want to play with your compiler+module LLVM.PassManager (+ PassManager,+ PassSetSpec(..), defaultPassSetSpec, defaultCuratedPassSetSpec,+ withPassManager,+ runPassManager+ ) where++import LLVM.Internal.PassManager
+ src/LLVM/Relocation.hs view
@@ -0,0 +1,12 @@+-- | Relocations, used in specifying TargetMachine+module LLVM.Relocation where++import LLVM.Prelude++-- | <http://llvm.org/doxygen/namespacellvm_1_1Reloc.html>+data Model + = Default+ | Static+ | PIC+ | DynamicNoPIC+ deriving (Eq, Read, Show, Typeable, Data)
+ src/LLVM/Target.hs view
@@ -0,0 +1,22 @@+-- | A 'Target' describes that for which code may be intended. Targets are used both during actual+-- | lowering of LLVM IR to machine code and by some optimization passes which use the target to+-- | judge costs.+module LLVM.Target (+ lookupTarget,+ TargetOptions,+ Target, TargetMachine, TargetLowering,+ CPUFeature(..),+ withTargetOptions, peekTargetOptions, pokeTargetOptions,+ withTargetMachine, withHostTargetMachine,+ getTargetLowering,+ getTargetMachineTriple, getDefaultTargetTriple, getProcessTargetTriple, getHostCPUName, getHostCPUFeatures,+ getTargetMachineDataLayout, initializeNativeTarget, initializeAllTargets,+ TargetLibraryInfo,+ getLibraryFunction,+ getLibraryFunctionName,+ setLibraryFunctionAvailableWithName,+ withTargetLibraryInfo+ ) where++import LLVM.Internal.Target+
+ src/LLVM/Target/LibraryFunction.hs view
@@ -0,0 +1,7 @@+-- | A 'LibraryFunction' identifies a function of which LLVM has particular knowledge.+module LLVM.Target.LibraryFunction (+ LibraryFunction(..)+ ) where+++import LLVM.Internal.LibraryFunction
+ src/LLVM/Target/Options.hs view
@@ -0,0 +1,41 @@+-- | <http://llvm.org/doxygen/classllvm_1_1TargetOptions.html>+module LLVM.Target.Options where++import LLVM.Prelude++-- | <http://llvm.org/doxygen/namespacellvm_1_1FloatABI.html#aea077c52d84934aabf9445cef9eab2e2>+data FloatABI+ = FloatABIDefault+ | FloatABISoft+ | FloatABIHard+ deriving (Eq, Ord, Read, Show, Enum, Bounded, Typeable, Data)++-- | <http://llvm.org/doxygen/namespacellvm_1_1FPOpFusion.html#a9c71bae9f02af273833fde586d529fc5>+data FloatingPointOperationFusionMode+ = FloatingPointOperationFusionFast+ | FloatingPointOperationFusionStandard+ | FloatingPointOperationFusionStrict+ deriving (Eq, Ord, Read, Show, Enum, Bounded, Typeable, Data)++-- | The options of a 'LLVM.Target.TargetOptions'+-- <http://llvm.org/doxygen/classllvm_1_1TargetOptions.html>+data Options = Options {+ printMachineCode :: Bool,+ lessPreciseFloatingPointMultiplyAddOption :: Bool,+ unsafeFloatingPointMath :: Bool,+ noInfinitiesFloatingPointMath :: Bool,+ noNaNsFloatingPointMath :: Bool,+ honorSignDependentRoundingFloatingPointMathOption :: Bool,+ noZerosInBSS :: Bool,+ guaranteedTailCallOptimization :: Bool,+ enableFastInstructionSelection :: Bool,+ useInitArray :: Bool,+ disableIntegratedAssembler :: Bool,+ compressDebugSections :: Bool,+ trapUnreachable :: Bool,+ stackAlignmentOverride :: Word32,+ floatABIType :: FloatABI,+ allowFloatingPointOperationFusion :: FloatingPointOperationFusionMode+ }+ deriving (Eq, Ord, Read, Show)+
+ src/LLVM/Threading.hs view
@@ -0,0 +1,24 @@+-- | functionality necessary when running LLVM in multiple threads at the same time.+module LLVM.Threading (+ setMultithreaded,+ isMultithreaded+ ) where++import LLVM.Prelude++import LLVM.Internal.Threading++{-# DEPRECATED setMultithreaded "LLVM no longer features runtime control of multithreading support" #-}+-- | This function used set the multithreading mode of LLVM, but that feature no longer exists. Threading is+-- controlled only at runtime with the configure flag --enable-threads (default is YES). This function will+-- now check that the the compiled-in multithreading support (returned by 'isMultithreaded') is+-- sufficient to support the requested access, and fail if not, so as to prevent uncontrolled use of a+-- version of LLVM compiled to be capable only of singled threaded use by haskell code requesting+-- multithreading support.+setMultithreaded :: Bool -> IO ()+setMultithreaded desired = do+ actual <- isMultithreaded+ when (desired && not actual) $+ fail $ "Multithreading support requested but not available. " ++ + "Please use an LLVM built with threading enabled"+ return ()
+ src/LLVM/Transforms.hs view
@@ -0,0 +1,197 @@+-- | This module provides an enumeration of the various transformation (e.g. optimization) passes+-- provided by LLVM. They can be used to create a 'LLVM.PassManager.PassManager' to, in turn,+-- run the passes on 'LLVM.Module.Module's. If you don't know what passes you want, consider+-- instead using 'LLVM.PassManager.CuratedPassSetSpec'.+module LLVM.Transforms where++import LLVM.Prelude++-- | <http://llvm.org/docs/Passes.html#transform-passes>+-- A few passes can make use of information in a 'LLVM.Target.TargetMachine' if one+-- is provided to 'LLVM.PassManager.createPassManager'.+-- <http://llvm.org/doxygen/classllvm_1_1Pass.html>+data Pass+ -- here begin the Scalar passes+ = AggressiveDeadCodeElimination+ | BreakCriticalEdges+ -- | can use a 'LLVM.Target.TargetMachine'+ | CodeGenPrepare+ | ConstantPropagation+ | CorrelatedValuePropagation+ | DeadCodeElimination+ | DeadInstructionElimination+ | DeadStoreElimination+ | DemoteRegisterToMemory+ | EarlyCommonSubexpressionElimination+ | GlobalValueNumbering { noLoads :: Bool }+ | InductionVariableSimplify+ | InstructionCombining+ | JumpThreading+ | LoopClosedSingleStaticAssignment+ | LoopInvariantCodeMotion+ | LoopDeletion+ | LoopIdiom+ | LoopInstructionSimplify+ | LoopRotate+ | LoopStrengthReduce+ | LoopUnroll { loopUnrollThreshold :: Maybe Word, count :: Maybe Word, allowPartial :: Maybe Bool }+ | LoopUnswitch { optimizeForSize :: Bool }+ | LowerAtomic+ | LowerInvoke+ | LowerSwitch+ | LowerExpectIntrinsic+ | MemcpyOptimization+ | PromoteMemoryToRegister+ | Reassociate+ | ScalarReplacementOfAggregates { requiresDominatorTree :: Bool }+ | OldScalarReplacementOfAggregates { + oldScalarReplacementOfAggregatesThreshold :: Maybe Word, + useDominatorTree :: Bool, + structMemberThreshold :: Maybe Word,+ arrayElementThreshold :: Maybe Word,+ scalarLoadThreshold :: Maybe Word+ }+ | SparseConditionalConstantPropagation+ | SimplifyLibCalls+ | SimplifyControlFlowGraph+ | Sinking+ | TailCallElimination++ -- here begin the Interprocedural passes+ | AlwaysInline { insertLifetime :: Bool }+ | ArgumentPromotion+ | ConstantMerge+ | FunctionAttributes+ | FunctionInlining { + functionInliningThreshold :: Word+ }+ | GlobalDeadCodeElimination+ | InternalizeFunctions { exportList :: [String] }+ | InterproceduralConstantPropagation+ | InterproceduralSparseConditionalConstantPropagation+ | MergeFunctions+ | PartialInlining+ | PruneExceptionHandling+ | StripDeadDebugInfo+ | StripDebugDeclare+ | StripNonDebugSymbols+ | StripSymbols { onlyDebugInfo :: Bool }++ -- here begin the vectorization passes+ | BasicBlockVectorize { + vectorBits :: Word,+ vectorizeBools :: Bool,+ vectorizeInts :: Bool,+ vectorizeFloats :: Bool,+ vectorizePointers :: Bool,+ vectorizeCasts :: Bool,+ vectorizeMath :: Bool,+ vectorizeFusedMultiplyAdd :: Bool,+ vectorizeSelect :: Bool,+ vectorizeCmp :: Bool,+ vectorizeGetElementPtr :: Bool,+ vectorizeMemoryOperations :: Bool,+ alignedOnly :: Bool,+ requiredChainDepth :: Word,+ searchLimit :: Word,+ maxCandidatePairsForCycleCheck :: Word,+ splatBreaksChain :: Bool,+ maxInstructions :: Word,+ maxIterations :: Word,+ powerOfTwoLengthsOnly :: Bool,+ noMemoryOperationBoost :: Bool,+ fastDependencyAnalysis :: Bool+ }+ | LoopVectorize {+ noUnrolling :: Bool,+ alwaysVectorize :: Bool+ }+ | SuperwordLevelParallelismVectorize++ -- here begin the instrumentation passes+ | GCOVProfiler {+ emitNotes :: Bool,+ emitData :: Bool,+ version :: GCOVVersion, + useCfgChecksum :: Bool,+ noRedZone :: Bool,+ functionNamesInData :: Bool+ }+ | AddressSanitizer+ | AddressSanitizerModule+ | MemorySanitizer {+ trackOrigins :: Bool+ }+ | ThreadSanitizer+ | BoundsChecking+ deriving (Eq, Ord, Read, Show, Typeable, Data)++-- | Defaults for the 'LoopVectorize' pass+defaultLoopVectorize :: Pass+defaultLoopVectorize = LoopVectorize {+ noUnrolling = False,+ alwaysVectorize = True+ }++-- | Defaults for the 'BasicBlockVectorize' pass - copied from the C++ code to keep these defaults+-- constant. (The C++ defaults are modifiable through global objects used for command-line processing,+-- in a design apparently oblivious to uses of LLVM besides the standard command-line tools).+defaultVectorizeBasicBlocks :: Pass+defaultVectorizeBasicBlocks = BasicBlockVectorize {+ vectorBits = 128,+ vectorizeBools = True,+ vectorizeInts = True,+ vectorizeFloats = True,+ vectorizePointers = True,+ vectorizeCasts = True,+ vectorizeMath = True,+ vectorizeFusedMultiplyAdd = True,+ vectorizeSelect = True,+ vectorizeCmp = True,+ vectorizeGetElementPtr = True,+ vectorizeMemoryOperations = True,+ alignedOnly = True,++ requiredChainDepth = 6,+ searchLimit = 400,+ maxCandidatePairsForCycleCheck = 200,+ splatBreaksChain = False,+ maxInstructions = 500,+ maxIterations = 0,+ powerOfTwoLengthsOnly = False,+ noMemoryOperationBoost = False,+ fastDependencyAnalysis = False+ }++-- | See <http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/gcov-io.h?view=markup>.+newtype GCOVVersion = GCOVVersion String+ deriving (Eq, Ord, Read, Show, Typeable, Data)++-- | Defaults for 'GCOVProfiler'.+defaultGCOVProfiler :: Pass+defaultGCOVProfiler = GCOVProfiler {+ emitNotes = True,+ emitData = True,+ version = GCOVVersion "402*", + useCfgChecksum = False,+ noRedZone = False,+ functionNamesInData = True+ }++-- | Defaults for 'AddressSanitizer'.+defaultAddressSanitizer :: Pass+defaultAddressSanitizer = AddressSanitizer++-- | Defaults for 'AddressSanitizerModule'.+defaultAddressSanitizerModule :: Pass+defaultAddressSanitizerModule = AddressSanitizerModule++-- | Defaults for 'MemorySanitizer'.+defaultMemorySanitizer :: Pass+defaultMemorySanitizer = MemorySanitizer {+ trackOrigins = False+}++-- | Defaults for 'ThreadSanitizer'.+defaultThreadSanitizer :: Pass+defaultThreadSanitizer = ThreadSanitizer
+ test/LLVM/Test/Analysis.hs view
@@ -0,0 +1,113 @@+module LLVM.Test.Analysis where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import Control.Monad.Trans.Except++import LLVM.Module+import LLVM.Context+import LLVM.Analysis++import LLVM.AST as A+import LLVM.AST.Type as A.T+import LLVM.AST.Name+import LLVM.AST.AddrSpace+import LLVM.AST.DataLayout+import qualified LLVM.AST.IntegerPredicate as IPred+import qualified LLVM.AST.Linkage as L+import qualified LLVM.AST.Visibility as V+import qualified LLVM.AST.CallingConvention as CC+import qualified LLVM.AST.Attribute as A+import qualified LLVM.AST.Global as G+import qualified LLVM.AST.Constant as C++import qualified LLVM.Relocation as R+import qualified LLVM.CodeModel as CM+import qualified LLVM.CodeGenOpt as CGO++tests = testGroup "Analysis" [+ testGroup "Verifier" [+{-+ -- this test will cause an assertion if LLVM is compiled with assertions on.+ testCase "Module" $ do+ let ast = Module "<string>" Nothing Nothing [+ GlobalDefinition $ Function L.External V.Default CC.C [] A.T.void (Name "foo") ([+ Parameter i32 (Name "x") []+ ],False)+ [] + Nothing 0 Nothing + [+ BasicBlock (UnName 0) [+ UnName 1 := Call {+ isTailCall = False,+ callingConvention = CC.C,+ returnAttributes = [],+ function = Right (ConstantOperand (C.GlobalReference (A.T.FunctionType A.T.void [A.T.i32] False) (Name "foo"))),+ arguments = [+ (ConstantOperand (C.Int 8 1), [])+ ],+ functionAttributes = [],+ metadata = []+ }+ ] (+ Do $ Ret Nothing []+ )+ ]+ ]+ Left s <- withContext $ \context -> withModuleFromAST' context ast $ runExceptT . verify+ s @?= "Call parameter type does not match function signature!\n\+ \i8 1\n\+ \ i32 call void @foo(i8 1)\n\+ \Broken module found, compilation terminated.\n\+ \Broken module found, compilation terminated.\n",+-}++ testGroup "regression" [+ testCase "load synchronization" $ do+ let str = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define double @my_function2(double* %input_0) {\n\+ \foo:\n\+ \ %tmp_input_w0 = getelementptr inbounds double, double* %input_0, i64 0\n\+ \ %0 = load double, double* %tmp_input_w0, align 8\n\+ \ ret double %0\n\+ \}\n"+ ast = + Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = double,+ G.name = Name "my_function2",+ G.parameters = ([+ Parameter (ptr double) (Name "input_0") []+ ],False),+ G.basicBlocks = [+ BasicBlock (Name "foo") [ + Name "tmp_input_w0" := GetElementPtr {+ inBounds = True,+ address = LocalReference (ptr double) (Name "input_0"),+ indices = [ConstantOperand (C.Int 64 0)],+ metadata = []+ },+ UnName 0 := Load {+ volatile = False,+ address = LocalReference (ptr double) (Name "tmp_input_w0"),+ maybeAtomicity = Nothing,+ alignment = 8,+ metadata = []+ }+ ] (+ Do $ Ret (Just (LocalReference double (UnName 0))) []+ )+ ]+ }+ ]+ strCheck ast str+ s <- withContext $ \context -> withModuleFromAST' context ast $ runExceptT . verify+ s @?= Right ()+ ]+ ]+ ]
+ test/LLVM/Test/CallingConvention.hs view
@@ -0,0 +1,57 @@+module LLVM.Test.CallingConvention where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import Data.Maybe+import qualified Data.Set as Set+import qualified Data.Map as Map++import LLVM.Context+import LLVM.Module+import LLVM.AST+import LLVM.AST.Type as T+import qualified LLVM.AST.CallingConvention as CC+import qualified LLVM.AST.Global as G++tests = testGroup "CallingConvention" [+ testCase name $ strCheck (defaultModule {+ moduleDefinitions = [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.callingConvention = cc+ }+ ]+ }) ("; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \declare" ++ (if name == "" then "" else (" " ++ name)) ++ " i32 @foo()\n")+ | (name, cc) <- [+ ("", CC.C),+ ("fastcc", CC.Fast),+ ("coldcc", CC.Cold),+ ("ghccc", CC.GHC),+ ("cc11", CC.HiPE),+ ("webkit_jscc", CC.WebKit_JS),+ ("anyregcc", CC.AnyReg),+ ("preserve_mostcc", CC.PreserveMost),+ ("preserve_allcc", CC.PreserveAll),+ ("x86_stdcallcc", CC.X86_StdCall),+ ("x86_fastcallcc", CC.X86_FastCall),+ ("arm_apcscc", CC.ARM_APCS),+ ("arm_aapcscc", CC.ARM_AAPCS),+ ("arm_aapcs_vfpcc", CC.ARM_AAPCS_VFP),+ ("msp430_intrcc", CC.MSP430_INTR),+ ("x86_thiscallcc", CC.X86_ThisCall),+ ("ptx_kernel", CC.PTX_Kernel),+ ("ptx_device", CC.PTX_Device),+ ("spir_func", CC.SPIR_FUNC),+ ("spir_kernel", CC.SPIR_KERNEL),+ ("intel_ocl_bicc", CC.Intel_OCL_BI),+ ("x86_64_sysvcc", CC.X86_64_SysV),+ ("x86_64_win64cc", CC.X86_64_Win64)+ ]+ ]
+ test/LLVM/Test/Constants.hs view
@@ -0,0 +1,184 @@+module LLVM.Test.Constants where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import Control.Monad+import Data.Functor+import Data.Maybe+import Foreign.Ptr+import Data.Word++import LLVM.Context+import LLVM.Module+import LLVM.Diagnostic+import LLVM.AST+import LLVM.AST.Type+import LLVM.AST.Name+import LLVM.AST.AddrSpace+import qualified LLVM.AST.Linkage as L+import qualified LLVM.AST.Visibility as V+import qualified LLVM.AST.CallingConvention as CC+import qualified LLVM.AST.Attribute as A+import qualified LLVM.AST.Global as G+import qualified LLVM.AST.Constant as C+import qualified LLVM.AST.Float as F+import qualified LLVM.AST.IntegerPredicate as IPred++tests = testGroup "Constants" [+ testCase name $ strCheck mAST mStr+ | (name, type', value, str) <- [+ (+ "integer",+ i32,+ C.Int 32 1,+ "global i32 1"+ ), (+ "wide integer",+ IntegerType 65,+ C.Int 65 1,+ "global i65 1"+ ), (+ "big wide integer",+ IntegerType 66,+ C.Int 66 20000000000000000000,+ "global i66 20000000000000000000"+ ), (+ "negative wide integer",+ IntegerType 65,+ C.Int 65 36893488147419103231,+ "global i65 -1"+ ), (+ "half",+ half,+ C.Float (F.Half 0x1234),+ "global half 0xH1234"+ ), (+ "float",+ float,+ C.Float (F.Single 1),+ "global float 1.000000e+00"+ ), (+ "double",+ double,+ C.Float (F.Double 1),+ "global double 1.000000e+00"+ ), (+ "quad",+ fp128,+ C.Float (F.Quadruple 0x0007000600050004 0x0003000200010000),+ "global fp128 0xL00030002000100000007000600050004" -- yes, this order is weird+ ), (+ "quad 1.0",+ fp128,+ C.Float (F.Quadruple 0x3fff000000000000 0x0000000000000000),+ "global fp128 0xL00000000000000003FFF000000000000" -- yes, this order is weird+ ), (+ "x86_fp80",+ x86_fp80,+ C.Float (F.X86_FP80 0x0004 0x0003000200010000),+ "global x86_fp80 0xK00040003000200010000"+{- don't know how to test this - LLVM's handling of this weird type is even weirder+ ), (+ "ppc_fp128",+ ppc_fp128,+ C.Float (F.PPC_FP128 0x0007000600050004 0x0003000200010000),+ "global ppc_fp128 0xM????????????????"+-}+ ), (+ "struct",+ StructureType False (replicate 2 i32),+ C.Struct Nothing False (replicate 2 (C.Int 32 1)),+ "global { i32, i32 } { i32 1, i32 1 }"+ ), (+ "dataarray",+ ArrayType 3 i32,+ C.Array i32 [C.Int 32 i | i <- [1,2,1]],+ "global [3 x i32] [i32 1, i32 2, i32 1]"+ ), (+ "array",+ ArrayType 3 (StructureType False [i32]),+ C.Array (StructureType False [i32]) [C.Struct Nothing False [C.Int 32 i] | i <- [1,2,1]],+ "global [3 x { i32 }] [{ i32 } { i32 1 }, { i32 } { i32 2 }, { i32 } { i32 1 }]"+ ), (+ "datavector",+ VectorType 3 i32,+ C.Vector [C.Int 32 i | i <- [1,2,1]],+ "global <3 x i32> <i32 1, i32 2, i32 1>"+ ), (+ "undef",+ i32,+ C.Undef i32,+ "global i32 undef"+ ), (+ "binop/cast",+ i64,+ C.Add False False (C.PtrToInt (C.GlobalReference (ptr i32) (UnName 1)) i64) (C.Int 64 2),+ "global i64 add (i64 ptrtoint (i32* @1 to i64), i64 2)"+ ), (+ "binop/cast nsw",+ i64,+ C.Add True False (C.PtrToInt (C.GlobalReference (ptr i32) (UnName 1)) i64) (C.Int 64 2),+ "global i64 add nsw (i64 ptrtoint (i32* @1 to i64), i64 2)"+ ), (+ "icmp",+ i1,+ C.ICmp IPred.SGE (C.GlobalReference (ptr i32) (UnName 1)) (C.GlobalReference (ptr i32) (UnName 2)),+ "global i1 icmp sge (i32* @1, i32* @2)"+ ), (+ "getelementptr",+ ptr i32,+ C.GetElementPtr True (C.GlobalReference (ptr i32) (UnName 1)) [C.Int 64 27],+ "global i32* getelementptr inbounds (i32, i32* @1, i64 27)"+ ), (+ "selectvalue",+ i32,+ C.Select (C.PtrToInt (C.GlobalReference (ptr i32) (UnName 1)) i1) + (C.Int 32 1)+ (C.Int 32 2),+ "global i32 select (i1 ptrtoint (i32* @1 to i1), i32 1, i32 2)"+ ), (+ "extractelement",+ i32,+ C.ExtractElement+ (C.BitCast+ (C.PtrToInt (C.GlobalReference (ptr i32) (UnName 1)) i64)+ (VectorType 2 i32))+ (C.Int 32 1),+ "global i32 extractelement (<2 x i32> bitcast (i64 ptrtoint (i32* @1 to i64) to <2 x i32>), i32 1)"+ ), (+ "addrspacecast",+ (PointerType i32 (AddrSpace 1)),+ C.AddrSpaceCast (C.GlobalReference (ptr i32) (UnName 1)) (PointerType i32 (AddrSpace 1)),+ "global i32 addrspace(1)* addrspacecast (i32* @1 to i32 addrspace(1)*)"+{-+ ), (+-- This test made llvm abort as of llvm-3.2. Now, as a new feature in llvm-3.4, it makes it report a fatal error!+ "extractvalue",+ i8,+ C.ExtractValue+ (C.Select (C.PtrToInt (C.GlobalReference (p i32) (UnName 1)) i1) + (C.Array i8 [C.Int 8 0])+ (C.Array i8 [C.Int 8 1]))+ [0],+ "global i8 extractvalue ([1 x i8] select (i1 ptrtoint (i32* @1 to i1), [1 x i8] [ i8 1 ], [1 x i8] [ i8 2 ]), 0)"+-}+ )+ ],+ let mAST = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 0, G.type' = type', G.initializer = Just value + },+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 1, G.type' = i32, G.initializer = Nothing + },+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 2, G.type' = i32, G.initializer = Nothing + }+ ]+ mStr = "; ModuleID = '<string>'\nsource_filename = \"<string>\"\n\n@0 = " ++ str ++ "\n\+ \@1 = external global i32\n\+ \@2 = external global i32\n"+ ]
+ test/LLVM/Test/DataLayout.hs view
@@ -0,0 +1,86 @@+module LLVM.Test.DataLayout where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import Data.Maybe+import qualified Data.Set as Set+import qualified Data.Map as Map++import LLVM.Context+import LLVM.Module+import LLVM.AST+import LLVM.AST.DataLayout+import LLVM.AST.AddrSpace+import qualified LLVM.AST.Global as G++m s = "; ModuleID = '<string>'\nsource_filename = \"<string>\"\n" ++ s+t s = "target datalayout = \"" ++ s ++ "\"\n"+ddl = defaultDataLayout BigEndian++tests = testGroup "DataLayout" [+ testCase name $ strCheckC (Module "<string>" "<string>" mdl Nothing []) (m sdl) (m sdlc)+ | (name, mdl, sdl, sdlc) <- [+ ("none", Nothing, "", "")+ ] ++ [+ (name, Just mdl, t sdl, t (fromMaybe sdl msdlc))+ | (name, mdl, sdl, msdlc) <- [+ ("little-endian", defaultDataLayout LittleEndian, "e", Nothing),+ ("big-endian", defaultDataLayout BigEndian, "E", Nothing),+ ("native", ddl { nativeSizes = Just (Set.fromList [8,32]) }, "E-n8:32", Nothing),+ (+ "no pref",+ ddl {+ pointerLayouts = + Map.singleton+ (AddrSpace 0) + (+ 8,+ AlignmentInfo {+ abiAlignment = 64,+ preferredAlignment = Nothing+ }+ )+ },+ "E-p:8:64",+ Nothing+ ), (+ "no pref",+ ddl {+ pointerLayouts = + Map.insert (AddrSpace 1) (8, AlignmentInfo 32 (Just 64)) (pointerLayouts ddl)+ },+ "E-p1:8:32:64",+ Nothing+ ), (+ "big",+ ddl {+ endianness = LittleEndian,+ mangling = Just ELFMangling,+ stackAlignment = Just 128,+ pointerLayouts = Map.fromList [+ (AddrSpace 0, (8, AlignmentInfo {abiAlignment = 8, preferredAlignment = Just 16}))+ ],+ typeLayouts = Map.fromList [+ ((IntegerAlign, 1), AlignmentInfo {abiAlignment = 8, preferredAlignment = Just 256}),+ ((IntegerAlign, 8), AlignmentInfo {abiAlignment = 8, preferredAlignment = Just 256}),+ ((IntegerAlign, 16), AlignmentInfo {abiAlignment = 16, preferredAlignment = Just 256}),+ ((IntegerAlign, 32), AlignmentInfo {abiAlignment = 32, preferredAlignment = Just 256}),+ ((IntegerAlign, 64), AlignmentInfo {abiAlignment = 64, preferredAlignment = Just 256}),+ ((VectorAlign, 64), AlignmentInfo {abiAlignment = 64, preferredAlignment = Just 256}),+ ((VectorAlign, 128), AlignmentInfo {abiAlignment = 128, preferredAlignment = Just 256}),+ ((FloatAlign, 32), AlignmentInfo {abiAlignment = 32, preferredAlignment = Just 256}),+ ((FloatAlign, 64), AlignmentInfo {abiAlignment = 64, preferredAlignment = Just 256}),+ ((FloatAlign, 80), AlignmentInfo {abiAlignment = 128, preferredAlignment = Just 256})+ ] `Map.union` typeLayouts ddl, + aggregateLayout = AlignmentInfo {abiAlignment = 0, preferredAlignment = Just 256},+ nativeSizes = Just (Set.fromList [8,16,32,64])+ },+ "e-m:e-p:8:8:16-i1:8:256-i8:8:256-i16:16:256-i32:32:256-i64:64:256-v64:64:256-v128:128:256-f32:32:256-f64:64:256-f80:128:256-a:0:256-n8:16:32:64-S128",+ Nothing+ )+ ]+ ]+ ]
+ test/LLVM/Test/ExecutionEngine.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE+ ForeignFunctionInterface+ #-}+module LLVM.Test.ExecutionEngine where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import Control.Monad+import Data.Functor+import Data.Maybe++import Foreign.Ptr+import Data.Word++import LLVM.Context+import LLVM.Module+import LLVM.ExecutionEngine+import LLVM.AST+import LLVM.AST.Type+import LLVM.AST.Name+import LLVM.AST.AddrSpace+import qualified LLVM.AST.IntegerPredicate as IPred++import qualified LLVM.AST.Linkage as L+import qualified LLVM.AST.Visibility as V+import qualified LLVM.AST.CallingConvention as CC+import qualified LLVM.AST.Attribute as A+import qualified LLVM.AST.Global as G+import qualified LLVM.AST.Constant as C++foreign import ccall "dynamic" mkIO32Stub :: FunPtr (Word32 -> IO Word32) -> (Word32 -> IO Word32)++testJIT :: ExecutionEngine e (FunPtr ()) => (Context -> (e -> IO ()) -> IO ()) -> Assertion+testJIT withEE = withContext $ \context -> withEE context $ \executionEngine -> do+ let mAST = Module "runSomethingModule" "runSomethingModule" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "_foo",+ G.parameters = ([Parameter i32 (Name "bar") []],False),+ G.basicBlocks = [+ BasicBlock (UnName 0) [] (+ Do $ Ret (Just (ConstantOperand (C.Int 32 42))) []+ )+ ]+ }+ ]++ s <- withModuleFromAST' context mAST $ \m -> do+ withModuleInEngine executionEngine m $ \em -> do+ Just p <- getFunction em (Name "_foo")+ (mkIO32Stub ((castFunPtr p) :: FunPtr (Word32 -> IO Word32))) 7+ s @?= 42++tests = testGroup "ExecutionEngine" [+ testCase "run something with MCJIT" $ testJIT (\c -> withMCJIT c Nothing Nothing Nothing Nothing)+ ]
+ test/LLVM/Test/Global.hs view
@@ -0,0 +1,42 @@+module LLVM.Test.Global where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import LLVM.Context+import LLVM.Module+import LLVM.AST+import LLVM.AST.Type as A.T+import qualified LLVM.AST.Global as G++tests = testGroup "Global" [+ testGroup "Alignment" [+ testCase name $ withContext $ \context -> do+ let ast = Module "<string>" "<string>" Nothing Nothing [ GlobalDefinition g ]+ ast' <- withModuleFromAST' context ast moduleAST+ ast' @?= ast+ | a <- [0,1],+ s <- [Nothing, Just "foo"],+ g <- [+ globalVariableDefaults {+ G.name = UnName 0,+ G.type' = i32,+ G.alignment = a,+ G.section = s+ },+ functionDefaults {+ G.returnType = A.T.void,+ G.name = UnName 0,+ G.parameters = ([], False),+ G.alignment = a,+ G.section = s+ }+ ],+ let+ gn (G.Function {}) = "function"+ gn (G.GlobalVariable {}) = "variable"+ name = gn g ++ ", align " ++ show a ++ (maybe "" (" section " ++ ) s)+ ]+ ]
+ test/LLVM/Test/InlineAssembly.hs view
@@ -0,0 +1,81 @@+module LLVM.Test.InlineAssembly where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import LLVM.Context+import LLVM.Module++import LLVM.AST+import LLVM.AST.Type+import LLVM.AST.InlineAssembly as IA+import qualified LLVM.AST.Linkage as L+import qualified LLVM.AST.Visibility as V+import qualified LLVM.AST.CallingConvention as CC+import qualified LLVM.AST.Constant as C+import qualified LLVM.AST.Global as G++tests = testGroup "InlineAssembly" [+ testCase "expression" $ do+ let ast = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ + functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.parameters = ([Parameter i32 (Name "x") []],False),+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ UnName 1 := Call {+ tailCallKind = Nothing,+ callingConvention = CC.C,+ returnAttributes = [],+ function = Left $ InlineAssembly {+ IA.type' = FunctionType i32 [i32] False,+ assembly = "bswap $0",+ constraints = "=r,r",+ hasSideEffects = False,+ alignStack = False,+ dialect = ATTDialect+ },+ arguments = [+ (LocalReference i32 (Name "x"), [])+ ],+ functionAttributes = [],+ metadata = []+ }+ ] (+ Do $ Ret (Just (LocalReference i32 (UnName 1))) []+ )+ ]+ }++ ]+ s = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define i32 @foo(i32 %x) {\n\+ \ %1 = call i32 asm \"bswap $0\", \"=r,r\"(i32 %x)\n\+ \ ret i32 %1\n\+ \}\n"+ strCheck ast s,++ testCase "module" $ do+ let ast = Module "<string>" "<string>" Nothing Nothing [+ ModuleInlineAssembly "foo",+ ModuleInlineAssembly "bar",+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 0,+ G.type' = i32+ }+ ]+ s = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \module asm \"foo\"\n\+ \module asm \"bar\"\n\+ \\n\+ \@0 = external global i32\n"+ strCheck ast s+ ]
+ test/LLVM/Test/Instructions.hs view
@@ -0,0 +1,1235 @@+module LLVM.Test.Instructions where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import Control.Monad+import Data.Functor+import Data.List.NonEmpty (NonEmpty((:|)))+import Data.Maybe+import Foreign.Ptr+import Data.Word++import LLVM.Context+import LLVM.Module+import LLVM.Diagnostic+import LLVM.AST+import LLVM.AST.Type as A.T+import LLVM.AST.Name+import LLVM.AST.AddrSpace+import qualified LLVM.AST.IntegerPredicate as IPred+import qualified LLVM.AST.FloatingPointPredicate as FPPred+import qualified LLVM.AST.Linkage as L+import qualified LLVM.AST.Visibility as V+import qualified LLVM.AST.CallingConvention as CC+import qualified LLVM.AST.Attribute as A+import qualified LLVM.AST.Global as G+import qualified LLVM.AST.Constant as C+import qualified LLVM.AST.RMWOperation as RMWOp++tests = testGroup "Instructions" [+ testGroup "regular" [+ testCase name $ do+ let mAST = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = A.T.void,+ G.name = UnName 0,+ G.parameters = ([Parameter t (UnName n) [] | (t,n) <- zip ts [0..]], False),+ G.basicBlocks = [+ BasicBlock (UnName 7) [+ namedInstr+ ] (+ Do $ Ret Nothing []+ )+ ]+ }+ ]+ mStr = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define void @0(i32, float, i32*, i64, i1, <2 x i32>, { i32, i32 }) {\n\+ \ " ++ namedInstrS ++ "\n\+ \ ret void\n\+ \}\n"+ strCheck mAST mStr+ | let ts = [+ i32,+ float,+ ptr i32,+ i64,+ i1,+ VectorType 2 i32,+ StructureType False [i32, i32]+ ],+ let a i = LocalReference (ts !! fromIntegral i) (UnName i),+ (name, namedInstr, namedInstrS) <- (+ [+ (name, UnName 8 := instr, "%8 = " ++ instrS)+ | (name, instr, instrS) <- [+ ("add",+ Add {+ nsw = False,+ nuw = False,+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "add i32 %0, %0"),+ ("nsw",+ Add {+ nsw = True,+ nuw = False,+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "add nsw i32 %0, %0"),+ ("nuw",+ Add {+ nsw = False,+ nuw = True,+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "add nuw i32 %0, %0"),+ ("fadd",+ FAdd {+ fastMathFlags = NoFastMathFlags,+ operand0 = a 1,+ operand1 = a 1,+ metadata = [] + },+ "fadd float %1, %1"),+ ("sub",+ Sub {+ nsw = False,+ nuw = False,+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "sub i32 %0, %0"),+ ("fsub",+ FSub {+ fastMathFlags = NoFastMathFlags,+ operand0 = a 1,+ operand1 = a 1,+ metadata = [] + },+ "fsub float %1, %1"),+ ("mul",+ Mul {+ nsw = False,+ nuw = False,+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "mul i32 %0, %0"),+ ("fmul",+ FMul {+ fastMathFlags = NoFastMathFlags,+ operand0 = a 1,+ operand1 = a 1,+ metadata = [] + },+ "fmul float %1, %1"),+ ("udiv",+ UDiv {+ exact = False,+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "udiv i32 %0, %0"),+ ("exact",+ UDiv {+ exact = True,+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "udiv exact i32 %0, %0"),+ ("sdiv",+ SDiv {+ exact = False,+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "sdiv i32 %0, %0"),+ ("fdiv",+ FDiv {+ fastMathFlags = NoFastMathFlags,+ operand0 = a 1,+ operand1 = a 1,+ metadata = [] + },+ "fdiv float %1, %1"),+ ("urem",+ URem {+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "urem i32 %0, %0"),+ ("srem",+ SRem {+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "srem i32 %0, %0"),+ ("frem",+ FRem {+ fastMathFlags = NoFastMathFlags,+ operand0 = a 1,+ operand1 = a 1,+ metadata = [] + },+ "frem float %1, %1"),+ ("frem fast",+ FRem {+ fastMathFlags = UnsafeAlgebra,+ operand0 = a 1,+ operand1 = a 1,+ metadata = [] + },+ "frem fast float %1, %1"),+ ("shl",+ Shl {+ nsw = False,+ nuw = False,+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "shl i32 %0, %0"),+ ("ashr",+ AShr {+ exact = False,+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "ashr i32 %0, %0"),+ ("lshr",+ LShr {+ exact = False,+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "lshr i32 %0, %0"),+ ("and",+ And {+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "and i32 %0, %0"),+ ("or",+ Or {+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "or i32 %0, %0"),+ ("xor",+ Xor {+ operand0 = a 0,+ operand1 = a 0,+ metadata = [] + },+ "xor i32 %0, %0"),+ ("alloca",+ Alloca {+ allocatedType = i32,+ numElements = Nothing,+ alignment = 0,+ metadata = [] + },+ "alloca i32"),+ ("alloca tricky",+ Alloca {+ allocatedType = IntegerType 7,+ numElements = Just (ConstantOperand (C.Int 32 2)),+ alignment = 128,+ metadata = [] + },+ "alloca i7, i32 2, align 128"),+ ("load",+ Load {+ volatile = False,+ address = a 2,+ maybeAtomicity = Nothing,+ alignment = 0,+ metadata = [] + },+ "load i32, i32* %2"),+ ("volatile",+ Load {+ volatile = True,+ address = a 2,+ maybeAtomicity = Nothing,+ alignment = 0,+ metadata = [] + },+ "load volatile i32, i32* %2"),+ ("acquire",+ Load {+ volatile = False,+ address = a 2,+ maybeAtomicity = Just (CrossThread, Acquire),+ alignment = 1,+ metadata = [] + },+ "load atomic i32, i32* %2 acquire, align 1"),+ ("singlethread",+ Load {+ volatile = False,+ address = a 2,+ maybeAtomicity = Just (SingleThread, Monotonic),+ alignment = 1,+ metadata = [] + },+ "load atomic i32, i32* %2 singlethread monotonic, align 1"),+ ("GEP",+ GetElementPtr {+ inBounds = False,+ address = a 2,+ indices = [ a 0 ],+ metadata = [] + },+ "getelementptr i32, i32* %2, i32 %0"),+ ("inBounds",+ GetElementPtr {+ inBounds = True,+ address = a 2,+ indices = [ a 0 ],+ metadata = [] + },+ "getelementptr inbounds i32, i32* %2, i32 %0"),+ ("cmpxchg",+ CmpXchg {+ volatile = False,+ address = a 2,+ expected = a 0,+ replacement = a 0,+ atomicity = (CrossThread, Monotonic),+ failureMemoryOrdering = Monotonic,+ metadata = [] + },+ "cmpxchg i32* %2, i32 %0, i32 %0 monotonic monotonic"),+ ("atomicrmw",+ AtomicRMW {+ volatile = False,+ rmwOperation = RMWOp.UMax,+ address = a 2,+ value = a 0,+ atomicity = (CrossThread, Release),+ metadata = []+ },+ "atomicrmw umax i32* %2, i32 %0 release"),++ ("trunc",+ Trunc {+ operand0 = a 0,+ type' = i16,+ metadata = [] + },+ "trunc i32 %0 to i16"),+ ("zext",+ ZExt {+ operand0 = a 0,+ type' = i64,+ metadata = [] + },+ "zext i32 %0 to i64"),+ ("sext",+ SExt {+ operand0 = a 0,+ type' = i64,+ metadata = [] + },+ "sext i32 %0 to i64"),+ ("fptoui",+ FPToUI {+ operand0 = a 1,+ type' = i64,+ metadata = [] + },+ "fptoui float %1 to i64"),+ ("fptosi",+ FPToSI {+ operand0 = a 1,+ type' = i64,+ metadata = [] + },+ "fptosi float %1 to i64"),+ ("uitofp",+ UIToFP {+ operand0 = a 0,+ type' = float,+ metadata = [] + },+ "uitofp i32 %0 to float"),+ ("sitofp",+ SIToFP {+ operand0 = a 0,+ type' = float,+ metadata = [] + },+ "sitofp i32 %0 to float"),+ ("fptrunc",+ FPTrunc {+ operand0 = a 1,+ type' = half,+ metadata = [] + },+ "fptrunc float %1 to half"),+ ("fpext",+ FPExt {+ operand0 = a 1,+ type' = double,+ metadata = [] + },+ "fpext float %1 to double"),+ ("ptrtoint",+ PtrToInt {+ operand0 = a 2,+ type' = i32,+ metadata = [] + },+ "ptrtoint i32* %2 to i32"),+ ("inttoptr",+ IntToPtr {+ operand0 = a 0,+ type' = ptr i32,+ metadata = [] + },+ "inttoptr i32 %0 to i32*"),+ ("bitcast",+ BitCast {+ operand0 = a 0,+ type' = float,+ metadata = [] + },+ "bitcast i32 %0 to float"),+ ("addrspacecast",+ AddrSpaceCast {+ operand0 = a 2,+ type' = PointerType i32 (AddrSpace 2),+ metadata = [] + },+ "addrspacecast i32* %2 to i32 addrspace(2)*"),+ ("select",+ Select {+ condition' = a 4,+ trueValue = a 0,+ falseValue = a 0,+ metadata = []+ },+ "select i1 %4, i32 %0, i32 %0"),+ ("vaarg",+ VAArg {+ argList = a 2,+ type' = i16,+ metadata = []+ },+ "va_arg i32* %2, i16"),+ ("extractelement",+ ExtractElement {+ vector = a 5,+ index = a 0,+ metadata = []+ },+ "extractelement <2 x i32> %5, i32 %0"),+ ("insertelement",+ InsertElement {+ vector = a 5,+ element = a 0,+ index = a 0,+ metadata = []+ },+ "insertelement <2 x i32> %5, i32 %0, i32 %0"),+ ("shufflevector",+ ShuffleVector {+ operand0 = a 5,+ operand1 = a 5,+ mask = C.Vector [ C.Int 32 p | p <- [0..1] ],+ metadata = []+ },+ "shufflevector <2 x i32> %5, <2 x i32> %5, <2 x i32> <i32 0, i32 1>"),+ ("extractvalue",+ ExtractValue {+ aggregate = a 6,+ indices' = [0],+ metadata = []+ },+ "extractvalue { i32, i32 } %6, 0"),+ ("insertvalue",+ InsertValue {+ aggregate = a 6,+ element = a 0,+ indices' = [0],+ metadata = []+ },+ "insertvalue { i32, i32 } %6, i32 %0, 0")+ ] ++ [+ ("landingpad-" ++ n,+ LandingPad {+ type' = StructureType False [ + ptr i8,+ i32+ ],+ cleanup = cp,+ clauses = cls,+ metadata = []+ },+ "landingpad { i8*, i32 }" ++ s)+ | (clsn,cls,clss) <- [+ ("catch",+ [Catch (C.Null (ptr i8))],+ "\n catch i8* null"),+ ("filter",+ [Filter (C.Null (ArrayType 1 (ptr i8)))],+ "\n filter [1 x i8*] zeroinitializer")+ ],+ (cpn, cp, cps) <- [ ("-cleanup", True, "\n cleanup"), ("", False, "") ],+ let s = cps ++ clss+ n = clsn ++ cpn+ ] ++ [+ ("icmp-" ++ ps,+ ICmp { iPredicate = p, operand0 = a 0, operand1 = a 0, metadata = [] },+ "icmp " ++ ps ++ " i32 %0, %0")+ | (ps, p) <- [+ ("eq", IPred.EQ),+ ("ne", IPred.NE),+ ("ugt", IPred.UGT),+ ("uge", IPred.UGE),+ ("ult", IPred.ULT),+ ("ule", IPred.ULE),+ ("sgt", IPred.SGT),+ ("sge", IPred.SGE),+ ("slt", IPred.SLT),+ ("sle", IPred.SLE)+ ]+ ] ++ [+ ("fcmp-" ++ ps,+ FCmp { fpPredicate = p, operand0 = a 1, operand1 = a 1, metadata = [] },+ "fcmp " ++ ps ++ " float %1, %1")+ | (ps, p) <- [+ ("false", FPPred.False),+ ("oeq", FPPred.OEQ),+ ("ogt", FPPred.OGT),+ ("oge", FPPred.OGE),+ ("olt", FPPred.OLT),+ ("ole", FPPred.OLE),+ ("one", FPPred.ONE),+ ("ord", FPPred.ORD),+ ("uno", FPPred.UNO),+ ("ueq", FPPred.UEQ),+ ("ugt", FPPred.UGT),+ ("uge", FPPred.UGE),+ ("ult", FPPred.ULT),+ ("ule", FPPred.ULE),+ ("une", FPPred.UNE),+ ("true", FPPred.True)+ ]+ ]+ ] ++ [+ ("store",+ Do $ Store {+ volatile = False,+ address = a 2,+ value = a 0,+ maybeAtomicity = Nothing,+ alignment = 0,+ metadata = [] + },+ "store i32 %0, i32* %2"),+ ("fence",+ Do $ Fence {+ atomicity = (CrossThread, Acquire),+ metadata = [] + },+ "fence acquire"),+ ("call",+ Do $ Call {+ tailCallKind = Nothing,+ callingConvention = CC.C,+ returnAttributes = [],+ function = Right (ConstantOperand (C.GlobalReference (ptr (FunctionType A.T.void ts False)) (UnName 0))),+ arguments = [ (a i, []) | i <- [0..6] ],+ functionAttributes = [],+ metadata = []+ },+ "call void @0(i32 %0, float %1, i32* %2, i64 %3, i1 %4, <2 x i32> %5, { i32, i32 } %6)")+ ]+ )+ ],+ testCase "GEP inBounds constant" $ do+ let mAST = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ globalVariableDefaults {+ G.name = Name "fortytwo",+ G.type' = i32,+ G.isConstant = True,+ G.initializer = Just $ C.Int 32 42+ },+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = UnName 0,+ G.basicBlocks = [+ BasicBlock (UnName 1) [+ UnName 2 := GetElementPtr {+ inBounds = True,+ address = ConstantOperand (C.GlobalReference (ptr i32) (Name "fortytwo")),+ indices = [ ConstantOperand (C.Int 32 0) ],+ metadata = []+ },+ UnName 3 := Load {+ volatile = False,+ address = LocalReference (ptr i32) (UnName 2),+ maybeAtomicity = Nothing,+ alignment = 1,+ metadata = []+ }+ ] (+ Do $ Ret (Just (LocalReference i32 (UnName 3))) []+ )+ ]+ }+ ]+ mStr = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \@0 = constant i32 42\n\+ \\n\+ \define i32 @1() {\n\+ \ %1 = load i32, i32* @0, align 1\n\+ \ ret i32 %1\n\+ \}\n"+ s <- withContext $ \context -> withModuleFromAST' context mAST moduleLLVMAssembly+ s @?= mStr,+ + testGroup "terminators" [+ testCase name $ strCheck mAST mStr+ | (name, mAST, mStr) <- [+ (+ "ret",+ Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = A.T.void,+ G.name = UnName 0,+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ ] (+ Do $ Ret Nothing []+ )+ ]+ }+ ],+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define void @0() {\n\+ \ ret void\n\+ \}\n"+ ), (+ "br",+ Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = A.T.void,+ G.name = UnName 0,+ G.basicBlocks = [+ BasicBlock (UnName 0) [] (+ Do $ Br (Name "foo") []+ ),+ BasicBlock (Name "foo") [] (+ Do $ Ret Nothing []+ )+ ]+ }+ ],+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define void @0() {\n\+ \ br label %foo\n\+ \\n\+ \foo: ; preds = %0\n\+ \ ret void\n\+ \}\n"+ ), (+ "condbr",+ Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = A.T.void,+ G.name = UnName 0,+ G.basicBlocks = [+ BasicBlock (Name "bar") [] (+ Do $ CondBr (ConstantOperand (C.Int 1 1)) (Name "foo") (Name "bar") []+ ),+ BasicBlock (Name "foo") [] (+ Do $ Ret Nothing []+ )+ ]+ }+ ],+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define void @0() {\n\+ \bar:\n\+ \ br i1 true, label %foo, label %bar\n\+ \\n\+ \foo: ; preds = %bar\n\+ \ ret void\n\+ \}\n"+ ), (+ "switch",+ Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = A.T.void,+ G.name = UnName 0,+ G.basicBlocks = [+ BasicBlock (UnName 0) [] (+ Do $ Switch {+ operand0' = ConstantOperand (C.Int 16 2),+ defaultDest = Name "foo",+ dests = [+ (C.Int 16 0, UnName 0),+ (C.Int 16 2, Name "foo"),+ (C.Int 16 3, UnName 0)+ ],+ metadata' = []+ }+ ),+ BasicBlock (Name "foo") [] (+ Do $ Ret Nothing []+ )+ ]+ }+ ],+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define void @0() {\n\+ \; <label>:0:\n\+ \ switch i16 2, label %foo [\n\+ \ i16 0, label %0\n\+ \ i16 2, label %foo\n\+ \ i16 3, label %0\n\+ \ ]\n\+ \\n\+ \foo: ; preds = %0, %0\n\+ \ ret void\n\+ \}\n"+ ), (+ "indirectbr",+ Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 0,+ G.type' = ptr i8,+ G.initializer = Just (C.BlockAddress (Name "foo") (UnName 2))+ },+ GlobalDefinition $ functionDefaults {+ G.returnType = A.T.void,+ G.name = Name "foo",+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ UnName 1 := Load {+ volatile = False,+ address = ConstantOperand (C.GlobalReference (ptr (ptr i8)) (UnName 0)),+ maybeAtomicity = Nothing,+ alignment = 0,+ metadata = [] + }+ ] (+ Do $ IndirectBr {+ operand0' = LocalReference (ptr i8) (UnName 1),+ possibleDests = [UnName 2],+ metadata' = []+ }+ ),+ BasicBlock (UnName 2) [] (+ Do $ Ret Nothing []+ )+ ]+ }+ ],+-- \ indirectbr i8* null, [label %foo]\n\+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \@0 = global i8* blockaddress(@foo, %2)\n\+ \\n\+ \define void @foo() {\n\+ \ %1 = load i8*, i8** @0\n\+ \ indirectbr i8* %1, [label %2]\n\+ \\n\+ \; <label>:2: ; preds = %0\n\+ \ ret void\n\+ \}\n"+ ), (+ "invoke",+ Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = A.T.void,+ G.name = UnName 0,+ G.personalityFunction = Just $ C.GlobalReference+ (ptr (FunctionType A.T.void [i32,i16] False))+ (UnName 0)+ ,+ G.parameters = ([+ Parameter i32 (UnName 0) [],+ Parameter i16 (UnName 1) []+ ], False),+ G.basicBlocks = [+ BasicBlock (UnName 2) [] (+ Do $ Invoke {+ callingConvention' = CC.C,+ returnAttributes' = [],+ function' = Right (ConstantOperand (C.GlobalReference (ptr (FunctionType A.T.void [i32, i16] False)) (UnName 0))),+ arguments' = [+ (ConstantOperand (C.Int 32 4), []),+ (ConstantOperand (C.Int 16 8), [])+ ],+ functionAttributes' = [],+ returnDest = Name "foo",+ exceptionDest = Name "bar",+ metadata' = []+ }+ ),+ BasicBlock (Name "foo") [] (+ Do $ Ret Nothing []+ ),+ BasicBlock (Name "bar") [+ UnName 3 := LandingPad {+ type' = StructureType False [+ ptr i8,+ i32+ ],+ cleanup = True,+ clauses = [Catch (C.Null (ptr i8))],+ metadata = []+ }+ ] (+ Do $ Ret Nothing []+ )+ ]+ }+ ],+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define void @0(i32, i16) personality void (i32, i16)* @0 {\n\+ \ invoke void @0(i32 4, i16 8)\n\+ \ to label %foo unwind label %bar\n\+ \\n\+ \foo: ; preds = %2\n\+ \ ret void\n\+ \\n\+ \bar: ; preds = %2\n\+ \ %3 = landingpad { i8*, i32 }\n\+ \ cleanup\n\+ \ catch i8* null\n\+ \ ret void\n\+ \}\n"+ ), (+ "resume",+ Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = A.T.void,+ G.name = UnName 0,+ G.basicBlocks = [+ BasicBlock (UnName 0) [] (+ Do $ Resume (ConstantOperand (C.Int 32 1)) []+ )+ ]+ }+ ],+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define void @0() {\n\+ \ resume i32 1\n\+ \}\n"+ ), (+ "unreachable",+ Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = A.T.void,+ G.name = UnName 0,+ G.basicBlocks = [+ BasicBlock (UnName 0) [] (+ Do $ Unreachable []+ )+ ]+ }+ ],+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define void @0() {\n\+ \ unreachable\n\+ \}\n"+ ), ( -- This testcase is taken from test/Feature/exception.ll in LLVM+ "cleanupret0",+ Module {+ moduleName = "<string>",+ moduleSourceFileName = "<string>",+ moduleDataLayout = Nothing,+ moduleTargetTriple = Nothing,+ moduleDefinitions = [+ GlobalDefinition functionDefaults {+ G.returnType = VoidType,+ G.name = Name "_Z3quxv"+ },+ GlobalDefinition functionDefaults {+ G.returnType = IntegerType {typeBits = 32},+ G.name = Name "__gxx_personality_v0",+ G.parameters = ([], True)+ },+ GlobalDefinition functionDefaults {+ G.returnType = VoidType,+ G.name = Name "cleanupret0",+ G.basicBlocks = [+ G.BasicBlock (Name "entry") [] (+ Do Invoke {+ callingConvention' = CC.C,+ returnAttributes' = [],+ function' = Right (+ ConstantOperand (+ C.GlobalReference PointerType {+ pointerReferent = FunctionType {resultType = VoidType, argumentTypes = [], isVarArg = False},+ pointerAddrSpace = AddrSpace 0+ } (Name "_Z3quxv")+ )+ ),+ arguments' = [],+ returnDest = Name "exit",+ exceptionDest = Name "pad",+ metadata' = [],+ functionAttributes' = []+ }+ ),+ G.BasicBlock+ (Name "pad")+ [Name "cp" := CleanupPad { parentPad = ConstantOperand C.TokenNone, args = [ConstantOperand C.Int { C.integerBits = 7, C.integerValue = 4 }], metadata = [] }]+ (+ Do CleanupRet {+ cleanupPad = LocalReference TokenType (Name "cp"),+ unwindDest = Nothing,+ metadata' = []+ }+ ),+ G.BasicBlock (Name "exit") [] (Do Ret { returnOperand = Nothing, metadata' = [] })+ ],+ G.personalityFunction = Just (+ C.GlobalReference PointerType {+ pointerReferent = FunctionType {resultType = IntegerType { typeBits = 32 }, argumentTypes = [], isVarArg = True},+ pointerAddrSpace = AddrSpace 0+ } (Name "__gxx_personality_v0")+ )+ }+ ]+ },+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \declare void @_Z3quxv()\n\+ \\n\+ \declare i32 @__gxx_personality_v0(...)\n\+ \\n\+ \define void @cleanupret0() personality i32 (...)* @__gxx_personality_v0 {\n\+ \entry:\n\+ \ invoke void @_Z3quxv()\n\+ \ to label %exit unwind label %pad\n\+ \\n\+ \pad: ; preds = %entry\n\+ \ %cp = cleanuppad within none [i7 4]\n\+ \ cleanupret from %cp unwind to caller\n\+ \\n\+ \exit: ; preds = %entry\n\+ \ ret void\n\+ \}\n"+ ), ( -- This testcase is taken from test/Feature/exception.ll in LLVM+ "cleanupret1",+ Module {+ moduleName = "<string>",+ moduleSourceFileName = "<string>",+ moduleDataLayout = Nothing,+ moduleTargetTriple = Nothing,+ moduleDefinitions = [+ GlobalDefinition functionDefaults {+ G.returnType = VoidType,+ G.name = Name "_Z3quxv"+ },+ GlobalDefinition functionDefaults {+ G.returnType = IntegerType {typeBits = 32},+ G.name = Name "__gxx_personality_v0",+ G.parameters = ([], True)+ },+ GlobalDefinition functionDefaults {+ G.returnType = VoidType,+ G.name = Name "cleanupret1",+ G.basicBlocks = [+ G.BasicBlock (Name "entry") [] (+ Do Invoke {+ callingConvention' = CC.C,+ returnAttributes' = [],+ function' = Right (+ ConstantOperand (+ C.GlobalReference PointerType {+ pointerReferent = FunctionType {resultType = VoidType, argumentTypes = [], isVarArg = False},+ pointerAddrSpace = AddrSpace 0+ } (Name "_Z3quxv")+ )+ ),+ arguments' = [],+ returnDest = Name "exit",+ exceptionDest = Name "pad",+ metadata' = [],+ functionAttributes' = []+ }+ ),+ G.BasicBlock+ (Name "cleanup")+ []+ (Do CleanupRet {+ cleanupPad = LocalReference TokenType (Name "cp"),+ unwindDest = Nothing,+ metadata' = []+ }),+ G.BasicBlock+ (Name "pad")+ [Name "cp" := CleanupPad { parentPad = ConstantOperand C.TokenNone, args = [], metadata = [] }]+ (Do Br { dest = Name "cleanup", metadata' = [] }),+ G.BasicBlock (Name "exit") [] (Do Ret { returnOperand = Nothing, metadata' = [] })+ ],+ G.personalityFunction = Just (+ C.GlobalReference PointerType {+ pointerReferent = FunctionType {resultType = IntegerType { typeBits = 32 }, argumentTypes = [], isVarArg = True},+ pointerAddrSpace = AddrSpace 0+ } (Name "__gxx_personality_v0")+ )+ }+ ]+ },+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \declare void @_Z3quxv()\n\+ \\n\+ \declare i32 @__gxx_personality_v0(...)\n\+ \\n\+ \define void @cleanupret1() personality i32 (...)* @__gxx_personality_v0 {\n\+ \entry:\n\+ \ invoke void @_Z3quxv()\n\+ \ to label %exit unwind label %pad\n\+ \\n\+ \cleanup: ; preds = %pad\n\+ \ cleanupret from %cp unwind to caller\n\+ \\n\+ \pad: ; preds = %entry\n\+ \ %cp = cleanuppad within none []\n\+ \ br label %cleanup\n\+ \\n\+ \exit: ; preds = %entry\n\+ \ ret void\n\+ \}\n"+ ), ( -- This testcase is taken from test/Feature/exception.ll in LLVM+ "catchret0",+ Module {+ moduleName = "<string>",+ moduleSourceFileName = "<string>",+ moduleDataLayout = Nothing,+ moduleTargetTriple = Nothing,+ moduleDefinitions = [+ GlobalDefinition functionDefaults {+ G.returnType = VoidType,+ G.name = Name "_Z3quxv"+ },+ GlobalDefinition functionDefaults {+ G.returnType = IntegerType {typeBits = 32},+ G.name = Name "__gxx_personality_v0",+ G.parameters = ([], True)+ },+ GlobalDefinition functionDefaults {+ G.returnType = VoidType,+ G.name = Name "catchret0",+ G.basicBlocks = [+ G.BasicBlock (Name "entry") [] (+ Do Invoke {+ callingConvention' = CC.C,+ returnAttributes' = [],+ function' = Right (+ ConstantOperand (+ C.GlobalReference PointerType {+ pointerReferent = FunctionType {resultType = VoidType, argumentTypes = [], isVarArg = False},+ pointerAddrSpace = AddrSpace 0+ } (Name "_Z3quxv")+ )+ ),+ arguments' = [],+ returnDest = Name "exit",+ exceptionDest = Name "pad",+ metadata' = [],+ functionAttributes' = []+ }+ ),+ G.BasicBlock (Name "pad") [] (+ Name "cs1" := CatchSwitch {+ parentPad' = ConstantOperand C.TokenNone,+ catchHandlers = (Name "catch" :| []),+ defaultUnwindDest = Nothing,+ metadata' = []+ }+ ),+ G.BasicBlock+ (Name "catch")+ [Name "cp" := CatchPad { catchSwitch = LocalReference TokenType (Name "cs1"), args = [ConstantOperand C.Int { C.integerBits = 7, C.integerValue = 4 }], metadata = [] }] (+ Do CatchRet {+ catchPad = LocalReference TokenType (Name "cp"),+ successor = Name "exit",+ metadata' = []+ }+ ),+ G.BasicBlock (Name "exit") [] (Do Ret { returnOperand = Nothing, metadata' = [] })+ ],+ G.personalityFunction = Just (+ C.GlobalReference PointerType {+ pointerReferent = FunctionType {resultType = IntegerType { typeBits = 32 }, argumentTypes = [], isVarArg = True},+ pointerAddrSpace = AddrSpace 0+ } (Name "__gxx_personality_v0")+ )+ }+ ]+ },+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \declare void @_Z3quxv()\n\+ \\n\+ \declare i32 @__gxx_personality_v0(...)\n\+ \\n\+ \define void @catchret0() personality i32 (...)* @__gxx_personality_v0 {\n\+ \entry:\n\+ \ invoke void @_Z3quxv()\n\+ \ to label %exit unwind label %pad\n\+ \\n\+ \pad: ; preds = %entry\n\+ \ %cs1 = catchswitch within none [label %catch] unwind to caller\n\+ \\n\+ \catch: ; preds = %pad\n\+ \ %cp = catchpad within %cs1 [i7 4]\n\+ \ catchret from %cp to label %exit\n\+ \\n\+ \exit: ; preds = %catch, %entry\n\+ \ ret void\n\+ \}\n"+ ), ( -- This testcase is taken from test/Feature/exception.ll in LLVM+ "catchret1",+ Module {+ moduleName = "<string>",+ moduleSourceFileName = "<string>",+ moduleDataLayout = Nothing,+ moduleTargetTriple = Nothing,+ moduleDefinitions = [+ GlobalDefinition functionDefaults {+ G.returnType = VoidType,+ G.name = Name "_Z3quxv"+ },+ GlobalDefinition functionDefaults {+ G.returnType = IntegerType {typeBits = 32},+ G.name = Name "__gxx_personality_v0",+ G.parameters = ([], True)+ },+ GlobalDefinition functionDefaults {+ G.returnType = VoidType,+ G.name = Name "catchret0",+ G.basicBlocks = [+ G.BasicBlock (Name "entry") [] (+ Do Invoke {+ callingConvention' = CC.C,+ returnAttributes' = [],+ function' = Right (+ ConstantOperand (+ C.GlobalReference PointerType {+ pointerReferent = FunctionType {resultType = VoidType, argumentTypes = [], isVarArg = False},+ pointerAddrSpace = AddrSpace 0+ } (Name "_Z3quxv")+ )+ ),+ arguments' = [],+ returnDest = Name "exit",+ exceptionDest = Name "pad",+ metadata' = [],+ functionAttributes' = []+ }+ ),+ G.BasicBlock (Name "catchret") [] (+ Do CatchRet {+ catchPad = LocalReference TokenType (Name "cp"),+ successor = Name "exit",+ metadata' = []+ }+ ),+ G.BasicBlock (Name "pad") [] (+ Name "cs1" := CatchSwitch {+ parentPad' = ConstantOperand C.TokenNone,+ catchHandlers = (Name "catch" :| []),+ defaultUnwindDest = Nothing,+ metadata' = []+ }+ ),+ G.BasicBlock+ (Name "catch")+ [Name "cp" := CatchPad { catchSwitch = LocalReference TokenType (Name "cs1"), args = [ConstantOperand C.Int { C.integerBits = 7, C.integerValue = 4 }], metadata = [] }] (+ Do Br { dest = (Name "catchret"), metadata' = [] }+ ),+ G.BasicBlock (Name "exit") [] (Do Ret { returnOperand = Nothing, metadata' = [] })+ ],+ G.personalityFunction = Just (+ C.GlobalReference PointerType {+ pointerReferent = FunctionType {resultType = IntegerType { typeBits = 32 }, argumentTypes = [], isVarArg = True},+ pointerAddrSpace = AddrSpace 0+ } (Name "__gxx_personality_v0")+ )+ }+ ]+ },+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \declare void @_Z3quxv()\n\+ \\n\+ \declare i32 @__gxx_personality_v0(...)\n\+ \\n\+ \define void @catchret0() personality i32 (...)* @__gxx_personality_v0 {\n\+ \entry:\n\+ \ invoke void @_Z3quxv()\n\+ \ to label %exit unwind label %pad\n\+ \\n\+ \catchret: ; preds = %catch\n\+ \ catchret from %cp to label %exit\n\+ \\n\+ \pad: ; preds = %entry\n\+ \ %cs1 = catchswitch within none [label %catch] unwind to caller\n\+ \\n\+ \catch: ; preds = %pad\n\+ \ %cp = catchpad within %cs1 [i7 4]\n\+ \ br label %catchret\n\+ \\n\+ \exit: ; preds = %catchret, %entry\n\+ \ ret void\n\+ \}\n"+ )+ ]+ ]+ ]
+ test/LLVM/Test/Instrumentation.hs view
@@ -0,0 +1,159 @@+module LLVM.Test.Instrumentation where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import Control.Monad.Trans.Except +import Control.Monad.IO.Class++import Data.Functor hiding (void)+import qualified Data.List as List+import qualified Data.Set as Set+import qualified Data.Map as Map++import LLVM.Module+import LLVM.Context+import LLVM.PassManager+import LLVM.Transforms+import LLVM.Target++import LLVM.AST as A+import LLVM.AST.Type+import LLVM.AST.Name+import LLVM.AST.AddrSpace+import LLVM.AST.DataLayout+import qualified LLVM.AST.IntegerPredicate as IPred+import qualified LLVM.AST.Linkage as L+import qualified LLVM.AST.Visibility as V+import qualified LLVM.AST.CallingConvention as CC+import qualified LLVM.AST.Attribute as A+import qualified LLVM.AST.Global as G+import qualified LLVM.AST.Constant as C++instrument :: PassSetSpec -> A.Module -> IO A.Module+instrument s m = withContext $ \context -> withModuleFromAST' context m $ \mIn' -> do+ withPassManager s $ \pm -> runPassManager pm mIn'+ moduleAST mIn'++ast = do+ dl <- withHostTargetMachine getTargetMachineDataLayout+ triple <- liftIO getDefaultTargetTriple+ return $ Module "<string>" "<string>" (Just dl) (Just triple) [+ -- This function is needed for AddressSanitizerModule+ GlobalDefinition $ functionDefaults {+ G.returnType = void,+ G.name = Name "asan.module_ctor",+ G.basicBlocks = [BasicBlock (UnName 0) [] (Do (Ret Nothing []))]+ },+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.parameters = ([Parameter i128 (Name "x") []],False),+ G.basicBlocks = [+ BasicBlock (UnName 0) [] (Do $ Br (Name "checkDone") []),+ BasicBlock (Name "checkDone") [+ UnName 1 := Phi {+ type' = i128,+ incomingValues = [+ (LocalReference i128 (Name "x"), UnName 0),+ (LocalReference i128 (Name "x'"), Name "even"),+ (LocalReference i128 (Name "x''"), Name "odd")+ ],+ metadata = []+ },+ Name "count" := Phi {+ type' = i32,+ incomingValues = [+ (ConstantOperand (C.Int 32 1), UnName 0),+ (LocalReference i32 (Name "count'"), Name "even"),+ (LocalReference i32 (Name "count'"), Name "odd")+ ],+ metadata = []+ },+ Name "count'" := Add {+ nsw = False,+ nuw = False,+ operand0 = LocalReference i32 (Name "count"),+ operand1 = ConstantOperand (C.Int 32 1),+ metadata = []+ },+ Name "is one" := ICmp {+ iPredicate = IPred.EQ,+ operand0 = LocalReference i128 (UnName 1),+ operand1 = ConstantOperand (C.Int 128 1),+ metadata = []+ }+ ] (+ Do $ CondBr (LocalReference i1 (Name "is one")) (Name "done") (Name "checkOdd") []+ ),+ BasicBlock (Name "checkOdd") [+ Name "is odd" := Trunc (LocalReference i128 (UnName 1)) i1 []+ ] (+ Do $ CondBr (LocalReference i1 (Name "is odd")) (Name "odd") (Name "even") []+ ),+ BasicBlock (Name "even") [+ Name "x'" := UDiv True (LocalReference i128 (UnName 1)) (ConstantOperand (C.Int 128 2)) []+ ] (+ Do $ Br (Name "checkDone") []+ ),+ BasicBlock (Name "odd") [+ UnName 2 := Mul False False (LocalReference i128 (UnName 1)) (ConstantOperand (C.Int 128 3)) [],+ Name "x''" := Add False False (LocalReference i128 (UnName 2)) (ConstantOperand (C.Int 128 1)) []+ ] (+ Do $ Br (Name "checkDone") []+ ),+ BasicBlock (Name "done") [+ ] (+ Do $ Ret (Just (LocalReference i32 (Name "count'"))) []+ )+ ]+ },+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "main",+ G.parameters = ([+ Parameter i32 (Name "argc") [],+ Parameter (ptr (ptr i8)) (Name "argv") []+ ],False),+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ UnName 1 := Call {+ tailCallKind = Nothing,+ callingConvention = CC.C,+ returnAttributes = [],+ function = Right (ConstantOperand (C.GlobalReference (FunctionType i32 [i32, ptr (ptr i8)] False) (Name "foo"))),+ arguments = [+ (ConstantOperand (C.Int 128 9491828328), [])+ ],+ functionAttributes = [],+ metadata = []+ }+ ] (+ Do $ Ret (Just (LocalReference i32 (UnName 1))) []+ )+ ]+ }+ ]++tests = testGroup "Instrumentation" [+ testGroup "basic" [+ testCase n $ do+ triple <- getProcessTargetTriple + withTargetLibraryInfo triple $ \tli -> do+ Right dl <- runExceptT $ withHostTargetMachine getTargetMachineDataLayout+ Right ast <- runExceptT ast+ ast' <- instrument (defaultPassSetSpec { transforms = [p], dataLayout = Just dl, targetLibraryInfo = Just tli }) ast+ let names ast = [ n | GlobalDefinition d <- moduleDefinitions ast, Name n <- return (G.name d) ]+ (names ast') `List.intersect` (names ast) @?= names ast+ | (n,p) <- [+ ("GCOVProfiler", defaultGCOVProfiler),+ ("AddressSanitizer", defaultAddressSanitizer),+ ("AddressSanitizerModule", defaultAddressSanitizerModule),+ ("MemorySanitizer", defaultMemorySanitizer),+ ("ThreadSanitizer", defaultThreadSanitizer),+ ("BoundsChecking", BoundsChecking)--,+ ]+ ]+ ]
+ test/LLVM/Test/Linking.hs view
@@ -0,0 +1,66 @@+module LLVM.Test.Linking where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import Control.Monad.Trans.Except+import Data.Functor+import qualified Data.Set as Set+import qualified Data.Map as Map++import LLVM.Module+import LLVM.Context+import LLVM.PassManager+import LLVM.Transforms+import LLVM.Target++import LLVM.AST as A+import LLVM.AST.Type+import LLVM.AST.Name+import LLVM.AST.AddrSpace+import LLVM.AST.DataLayout+import qualified LLVM.AST.IntegerPredicate as IPred+import qualified LLVM.AST.Linkage as L+import qualified LLVM.AST.Visibility as V+import qualified LLVM.AST.CallingConvention as CC+import qualified LLVM.AST.Attribute as A+import qualified LLVM.AST.Global as G+import qualified LLVM.AST.Constant as C++tests = testGroup "Linking" [+ testCase "basic" $ do+ let + ast0 = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.linkage = L.Private,+ G.returnType = i32,+ G.name = Name "private0"+ },+ GlobalDefinition $ functionDefaults {+ G.linkage = L.External,+ G.returnType = i32,+ G.name = Name "external0"+ }+ ]+ ast1 = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.linkage = L.Private,+ G.returnType = i32,+ G.name = Name "private1"+ },+ GlobalDefinition $ functionDefaults {+ G.linkage = L.External,+ G.returnType = i32,+ G.name = Name "external1"+ }+ ] ++ Module { moduleDefinitions = defs } <- withContext $ \context -> + withModuleFromAST' context ast0 $ \dest -> do+ withModuleFromAST' context ast0 $ \src -> do+ failInIO $ linkModules dest src+ moduleAST dest+ [ n | GlobalDefinition g <- defs, let Name n = G.name g ] @?= [ "private0", "external0" ]+ ]
+ test/LLVM/Test/Metadata.hs view
@@ -0,0 +1,157 @@+module LLVM.Test.Metadata where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import LLVM.AST as A+import LLVM.AST.Type as A.T+import LLVM.AST.AddrSpace as A+import qualified LLVM.AST.Linkage as L+import qualified LLVM.AST.Visibility as V+import qualified LLVM.AST.CallingConvention as CC+import qualified LLVM.AST.Constant as C+import LLVM.AST.Global as G++tests = testGroup "Metadata" [+ -- testCase "local" $ do+ -- let ast = Module "<string>" Nothing Nothing [+ -- GlobalDefinition $ globalVariableDefaults { G.name = UnName 0, G.type' = i32 },+ -- GlobalDefinition $ functionDefaults {+ -- G.returnType = i32,+ -- G.name = Name "foo",+ -- G.basicBlocks = [+ -- BasicBlock (UnName 0) [+ -- UnName 1 := Load {+ -- volatile = False,+ -- address = ConstantOperand (C.GlobalReference (ptr i32) (UnName 0)),+ -- maybeAtomicity = Nothing,+ -- A.alignment = 0,+ -- metadata = []+ -- }+ -- ] (+ -- Do $ Ret (Just (ConstantOperand (C.Int 32 0))) [+ -- (+ -- "my-metadatum", + -- MetadataNode [+ -- Just $ MDValue $ LocalReference i32 (UnName 1),+ -- Just $ MDString "super hyper",+ -- Nothing+ -- ]+ -- )+ -- ]+ -- )+ -- ]+ -- }+ -- ]+ -- let s = "; ModuleID = '<string>'\n\+ -- \\n\+ -- \@0 = external global i32\n\+ -- \\n\+ -- \define i32 @foo() {\n\+ -- \ %1 = load i32, i32* @0\n\+ -- \ ret i32 0, !my-metadatum !{i32 %1, !\"super hyper\", null}\n\+ -- \}\n"+ -- strCheck ast s,++ testCase "global" $ do+ let ast = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ ] (+ Do $ Ret (Just (ConstantOperand (C.Int 32 0))) [+ ("my-metadatum", MetadataNodeReference (MetadataNodeID 0))+ ]+ )+ ]+ },+ MetadataNodeDefinition (MetadataNodeID 0) [ Just $ MDValue $ ConstantOperand (C.Int 32 1) ]+ ]+ let s = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define i32 @foo() {\n\+ \ ret i32 0, !my-metadatum !0\n\+ \}\n\+ \\n\+ \!0 = !{i32 1}\n"+ strCheck ast s,++ testCase "named" $ do+ let ast = Module "<string>" "<string>" Nothing Nothing [+ NamedMetadataDefinition "my-module-metadata" [ MetadataNodeID 0 ],+ MetadataNodeDefinition (MetadataNodeID 0) [ Just $ MDValue $ ConstantOperand (C.Int 32 1) ]+ ]+ let s = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \!my-module-metadata = !{!0}\n\+ \\n\+ \!0 = !{i32 1}\n"+ strCheck ast s,++ testCase "null" $ do+ let ast = Module "<string>" "<string>" Nothing Nothing [+ NamedMetadataDefinition "my-module-metadata" [ MetadataNodeID 0 ],+ MetadataNodeDefinition (MetadataNodeID 0) [ Nothing ]+ ]+ let s = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \!my-module-metadata = !{!0}\n\+ \\n\+ \!0 = !{null}\n"+ strCheck ast s,++ testGroup "cyclic" [+ testCase "metadata-only" $ do+ let ast = Module "<string>" "<string>" Nothing Nothing [+ NamedMetadataDefinition "my-module-metadata" [MetadataNodeID 0],+ MetadataNodeDefinition (MetadataNodeID 0) [+ Just $ MDNode (MetadataNodeReference (MetadataNodeID 1)) + ],+ MetadataNodeDefinition (MetadataNodeID 1) [+ Just $ MDNode (MetadataNodeReference (MetadataNodeID 0)) + ]+ ]+ let s = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \!my-module-metadata = !{!0}\n\+ \\n\+ \!0 = !{!1}\n\+ \!1 = !{!0}\n"+ strCheck ast s,++ testCase "metadata-global" $ do+ let ast = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = A.T.void,+ G.name = Name "foo",+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ ] (+ Do $ Ret Nothing [ ("my-metadatum", MetadataNodeReference (MetadataNodeID 0)) ]+ )+ ]+ },+ MetadataNodeDefinition (MetadataNodeID 0) [+ Just $ MDValue $ ConstantOperand (C.GlobalReference (ptr (FunctionType A.T.void [] False)) (Name "foo"))+ ]+ ]+ let s = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define void @foo() {\n\+ \ ret void, !my-metadatum !0\n\+ \}\n\+ \\n\+ \!0 = !{void ()* @foo}\n"+ strCheck ast s+ ]++ ]
+ test/LLVM/Test/Module.hs view
@@ -0,0 +1,574 @@+module LLVM.Test.Module where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import Control.Monad.Trans.Except+import Data.Bits+import Data.Word++import qualified Data.Map as Map++import LLVM.Context+import LLVM.Module+import LLVM.Analysis+import LLVM.Diagnostic+import LLVM.Target+import LLVM.AST+import LLVM.AST.Type as T+import LLVM.AST.AddrSpace+import qualified LLVM.AST.IntegerPredicate as IPred++import qualified LLVM.AST.Linkage as L+import qualified LLVM.AST.Visibility as V+import qualified LLVM.AST.DLL as DLL+import qualified LLVM.AST.CallingConvention as CC+import qualified LLVM.AST.FunctionAttribute as FA+import qualified LLVM.AST.ParameterAttribute as PA+import qualified LLVM.AST.ThreadLocalStorage as TLS+import qualified LLVM.AST.Global as G+import qualified LLVM.AST.Constant as C+import qualified LLVM.AST.COMDAT as COMDAT++import qualified LLVM.Relocation as R+import qualified LLVM.CodeModel as CM+import qualified LLVM.CodeGenOpt as CGO++handString = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \%0 = type { i32, %1*, %0* }\n\+ \%1 = type opaque\n\+ \\n\+ \$bob = comdat largest\n\+ \\n\+ \@0 = global i32 1\n\+ \@1 = external protected addrspace(3) global i32, section \"foo\", comdat($bob)\n\+ \@2 = unnamed_addr global i8 2\n\+ \@3 = external dllimport global %0\n\+ \@4 = external global [4294967296 x i32]\n\+ \@.argyle = thread_local global i32 0\n\+ \@5 = thread_local(localdynamic) global i32 1\n\+ \\n\+ \@three = private alias i32, i32 addrspace(3)* @1\n\+ \@two = unnamed_addr alias i32, i32 addrspace(3)* @three\n\+ \@one = thread_local(initialexec) alias i32, i32* @5\n\+ \\n\+ \define i32 @bar() prefix i32 1 {\n\+ \ %1 = musttail call zeroext i32 @foo(i32 inreg align 16 1, i8 signext 4) #0\n\+ \ ret i32 %1\n\+ \}\n\+ \\n\+ \; Function Attrs: nounwind readnone uwtable\n\+ \define zeroext i32 @foo(i32 inreg align 16 %x, i8 signext %y) #0 {\n\+ \ %1 = mul nsw i32 %x, %x\n\+ \ br label %here\n\+ \\n\+ \here: ; preds = %0\n\+ \ %go = icmp eq i32 %1, %x\n\+ \ br i1 %go, label %there, label %elsewhere\n\+ \\n\+ \there: ; preds = %here\n\+ \ %2 = add nsw i32 %1, 3\n\+ \ br label %elsewhere\n\+ \\n\+ \elsewhere: ; preds = %there, %here\n\+ \ %r = phi i32 [ 2, %there ], [ 57, %here ]\n\+ \ ret i32 %r\n\+ \}\n\+ \\n\+ \attributes #0 = { nounwind readnone uwtable \"eep\" }\n"++handAST = Module "<string>" "<string>" Nothing Nothing [+ TypeDefinition (UnName 0) (+ Just $ StructureType False [+ i32,+ ptr (NamedTypeReference (UnName 1)),+ ptr (NamedTypeReference (UnName 0))+ ]),+ TypeDefinition (UnName 1) Nothing,+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 0,+ G.type' = i32,+ G.initializer = Just (C.Int 32 1)+ },+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 1,+ G.visibility = V.Protected,+ G.type' = i32,+ G.addrSpace = AddrSpace 3,+ G.section = Just "foo",+ G.comdat = Just "bob"+ },+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 2,+ G.unnamedAddr = Just GlobalAddr,+ G.type' = i8,+ G.initializer = Just (C.Int 8 2)+ },+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 3,+ G.dllStorageClass = Just DLL.Import,+ G.type' = NamedTypeReference (UnName 0)+ },+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 4,+ G.type' = ArrayType (1 `shift` 32) i32+ },+ GlobalDefinition $ globalVariableDefaults {+ G.name = Name ".argyle",+ G.type' = i32,+ G.initializer = Just (C.Int 32 0),+ G.threadLocalMode = Just TLS.GeneralDynamic+ },+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 5,+ G.type' = i32,+ G.threadLocalMode = Just TLS.LocalDynamic,+ G.initializer = Just (C.Int 32 1)+ },+ GlobalDefinition $ globalAliasDefaults {+ G.name = Name "three",+ G.linkage = L.Private,+ G.type' = PointerType i32 (AddrSpace 3),+ G.aliasee = C.GlobalReference (PointerType i32 (AddrSpace 3)) (UnName 1)+ },+ GlobalDefinition $ globalAliasDefaults {+ G.name = Name "two",+ G.unnamedAddr = Just GlobalAddr,+ G.type' = PointerType i32 (AddrSpace 3),+ G.aliasee = C.GlobalReference (PointerType i32 (AddrSpace 3)) (Name "three")+ },+ GlobalDefinition $ globalAliasDefaults {+ G.name = Name "one",+ G.type' = ptr i32,+ G.aliasee = C.GlobalReference (ptr i32) (UnName 5),+ G.threadLocalMode = Just TLS.InitialExec+ },+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "bar",+ G.prefix = Just (C.Int 32 1),+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ UnName 1 := Call {+ tailCallKind = Just MustTail,+ callingConvention = CC.C,+ returnAttributes = [PA.ZeroExt],+ function = Right (ConstantOperand (C.GlobalReference (ptr (FunctionType i32 [i32, i8] False)) (Name "foo"))),+ arguments = [+ (ConstantOperand (C.Int 32 1), [PA.InReg, PA.Alignment 16]),+ (ConstantOperand (C.Int 8 4), [PA.SignExt])+ ],+ functionAttributes = [Left (FA.GroupID 0)],+ metadata = []+ }+ ] (+ Do $ Ret (Just (LocalReference i32 (UnName 1))) []+ )+ ]+ },+ GlobalDefinition $ functionDefaults {+ G.returnAttributes = [PA.ZeroExt],+ G.returnType = i32,+ G.name = Name "foo",+ G.parameters = ([+ Parameter i32 (Name "x") [PA.InReg, PA.Alignment 16],+ Parameter i8 (Name "y") [PA.SignExt]+ ], False),+ G.functionAttributes = [Left (FA.GroupID 0)],+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ UnName 1 := Mul {+ nsw = True,+ nuw = False,+ operand0 = LocalReference i32 (Name "x"),+ operand1 = LocalReference i32 (Name "x"),+ metadata = []+ }+ ] (+ Do $ Br (Name "here") []+ ),+ BasicBlock (Name "here") [+ Name "go" := ICmp {+ iPredicate = IPred.EQ,+ operand0 = LocalReference i32 (UnName 1),+ operand1 = LocalReference i32 (Name "x"),+ metadata = []+ }+ ] (+ Do $ CondBr {+ condition = LocalReference i1 (Name "go"),+ trueDest = Name "there",+ falseDest = Name "elsewhere",+ metadata' = []+ }+ ),+ BasicBlock (Name "there") [+ UnName 2 := Add {+ nsw = True,+ nuw = False,+ operand0 = LocalReference i32 (UnName 1),+ operand1 = ConstantOperand (C.Int 32 3),+ metadata = []+ }+ ] (+ Do $ Br (Name "elsewhere") []+ ),+ BasicBlock (Name "elsewhere") [+ Name "r" := Phi {+ type' = i32,+ incomingValues = [+ (ConstantOperand (C.Int 32 2), Name "there"),+ (ConstantOperand (C.Int 32 57), Name "here")+ ],+ metadata = []+ }+ ] (+ Do $ Ret (Just (LocalReference i32 (Name "r"))) []+ )+ ]+ },+ FunctionAttributes (FA.GroupID 0) [FA.NoUnwind, FA.ReadNone, FA.UWTable, FA.StringAttribute "eep" ""],+ COMDAT "bob" COMDAT.Largest+ ]++tests = testGroup "Module" [+ testGroup "withModuleFromString" [+ testCase "basic" $ withContext $ \context -> do+ z <- withModuleFromLLVMAssembly' context handString (const $ return 0)+ z @?= 0,+ testCase "numbering" $ withContext $ \context -> do+ let s = "@0 = global i32 3\+ \define i32 @1(i32 %x) {\n\+ \ %1 = mul i32 %x, %x\n\+ \ %2 = add i32 %1, 3\n\+ \ ret i32 %2\n\+ \}\n"+ z <- withModuleFromLLVMAssembly' context s (const $ return 0)+ z @?= 0+ ],++ testGroup "emit" [+ testCase "assemble" $ withContext $ \context -> do+ let s = "define i32 @main(i32 %argc, i8** %argv) {\n\+ \ ret i32 0\n\+ \}\n"+ a <- withModuleFromLLVMAssembly' context s $ \m -> do+ (t, _) <- failInIO $ lookupTarget Nothing "x86_64-unknown-linux"+ withTargetOptions $ \to -> do+ withTargetMachine t "x86_64-unknown-linux" "" Map.empty to R.Default CM.Default CGO.Default $ \tm -> do+ failInIO $ moduleTargetAssembly tm m+ a @?= "\t.text\n\+ \\t.file\t\"<string>\"\n\+ \\t.globl\tmain\n\+ \\t.p2align\t4, 0x90\n\+ \\t.type\tmain,@function\n\+ \main:\n\+ \\t.cfi_startproc\n\+ \\txorl\t%eax, %eax\n\+ \\tretq\n\+ \.Lfunc_end0:\n\+ \\t.size\tmain, .Lfunc_end0-main\n\+ \\t.cfi_endproc\n\+ \\n\+ \\n\+ \\t.section\t\".note.GNU-stack\",\"\",@progbits\n"+ ],++ testCase "handStringIsCanonical" $ withContext $ \context -> do+ s <- withModuleFromLLVMAssembly' context handString moduleLLVMAssembly+ s @?= handString,++ testCase "moduleAST" $ withContext $ \context -> do+ ast <- withModuleFromLLVMAssembly' context handString moduleAST+ ast @?= handAST,+ + testCase "withModuleFromAST" $ withContext $ \context -> do+ s <- withModuleFromAST' context handAST moduleLLVMAssembly+ s @?= handString,++ testCase "bitcode" $ withContext $ \context -> do+ bs <- withModuleFromAST' context handAST moduleBitcode+ s <- withModuleFromBitcode' context bs moduleLLVMAssembly+ s @?= handString,++ testCase "triple" $ withContext $ \context -> do+ let hAST = "; ModuleID = '<string>'\n\+ \target triple = \"x86_64-unknown-linux\"\n"+ ast <- withModuleFromLLVMAssembly' context hAST moduleAST+ ast @?= defaultModule { moduleTargetTriple = Just "x86_64-unknown-linux" },++ testGroup "regression" [+ testCase "minimal type info" $ withContext $ \context -> do+ let s = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define void @trouble() {\n\+ \entry:\n\+ \ ret void\n\+ \\n\+ \dead0: ; preds = %dead1\n\+ \ %x0 = add i32 %x1, %x1\n\+ \ br label %dead1\n\+ \\n\+ \dead1: ; preds = %dead0\n\+ \ %x1 = add i32 %x0, %x0\n\+ \ br label %dead0\n\+ \}\n"+ ast = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = T.void,+ G.name = Name "trouble",+ G.basicBlocks = [+ BasicBlock (Name "entry") [+ ] (+ Do $ Ret Nothing []+ ),+ BasicBlock (Name "dead0") [+ Name "x0" := Add {+ nsw = False,+ nuw = False,+ operand0 = LocalReference i32 (Name "x1"),+ operand1 = LocalReference i32 (Name "x1"),+ metadata = []+ }+ ] (+ Do $ Br (Name "dead1") []+ ),+ BasicBlock (Name "dead1") [+ Name "x1" := Add {+ nsw = False,+ nuw = False,+ operand0 = LocalReference i32 (Name "x0"),+ operand1 = LocalReference i32 (Name "x0"),+ metadata = []+ }+ ] (+ Do $ Br (Name "dead0") []+ )+ ]+ }+ ]+ strCheck ast s+ s' <- withContext $ \context -> withModuleFromAST' context ast $ runExceptT . verify+ s' @?= Right (),++ testCase "metadata type" $ withContext $ \context -> do+ let s = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define void @bar(metadata) {\n\+ \ ret void\n\+ \}\n"+ ast = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = void,+ G.name = Name "bar",+ G.parameters = ([Parameter MetadataType (UnName 0) []], False),+ G.basicBlocks = [+ BasicBlock (UnName 1) [] (Do $ Ret Nothing [])+ ]+ }+ ]+ strCheck ast s,++ testCase "set flag on constant expr" $ withContext $ \context -> do+ let ast = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.parameters = ([Parameter i32 (Name "x") []], False),+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ UnName 1 := Mul {+ nsw = True,+ nuw = False,+ operand0 = ConstantOperand (C.Int 32 1),+ operand1 = ConstantOperand (C.Int 32 1),+ metadata = []+ }+ ] (+ Do $ Br (Name "here") []+ ),+ BasicBlock (Name "here") [+ ] (+ Do $ Ret (Just (LocalReference i32 (UnName 1))) []+ )+ ]+ }+ ]+ t <- withModuleFromAST' context ast $ \_ -> return True+ t @?= True,++ testCase "Phi node finishes" $ withContext $ \context -> do+ let ast = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.parameters = ([Parameter i32 (Name "x") []], False),+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ UnName 1 := Mul {+ nsw = True,+ nuw = False,+ operand0 = LocalReference i32 (Name "x"),+ operand1 = LocalReference i32 (Name "x"),+ metadata = []+ }+ ] (+ Do $ Br (Name "here") []+ ),+ BasicBlock (Name "here") [+ UnName 2 := Phi i32 [ (ConstantOperand (C.Int 32 42), UnName 0) ] []+ ] (+ Do $ Br (Name "elsewhere") []+ ),+ BasicBlock (Name "elsewhere") [ + ] (+ Do $ Br (Name "there") []+ ),+ BasicBlock (Name "there") [+ ] (+ Do $ Ret (Just (LocalReference i32 (UnName 1))) []+ )+ ]+ }+ ]+ s = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \define i32 @foo(i32 %x) {\n\+ \ %1 = mul nsw i32 %x, %x\n\+ \ br label %here\n\+ \\n\+ \here: ; preds = %0\n\+ \ %2 = phi i32 [ 42, %0 ]\n\+ \ br label %elsewhere\n\+ \\n\+ \elsewhere: ; preds = %here\n\+ \ br label %there\n\+ \\n\+ \there: ; preds = %elsewhere\n\+ \ ret i32 %1\n\+ \}\n"+ strCheck ast s,++ testCase "switchblock" $ do+ let count = 450+ start = 2 -- won't come back the same w/o start = 2+ ns = [start..count + start - 1]+ vbps = zip [ ConstantOperand (C.Int 32 i) | i <- [0..] ] [ UnName n | n <- (1:ns) ]+ cbps = zip [ C.Int 32 i | i <- [0..] ] [ UnName n | n <- ns ]++ withContext $ \context -> do+ let ast = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.name = Name "foo",+ G.returnType = i32,+ G.parameters = ([Parameter i32 (UnName 0) []], False),+ G.basicBlocks = [+ BasicBlock (UnName 1) [] (Do $ Switch (LocalReference i32 (UnName 0)) (Name "end") cbps [])+ ] ++ [+ BasicBlock (UnName n) [] (Do $ Br (Name "end") []) | n <- ns+ ] ++ [+ BasicBlock (Name "end") [+ Name "val" := Phi i32 vbps []+ ] (+ Do $ Ret (Just (LocalReference i32 (Name "val"))) []+ )+ ]+ }+ ]+ s <- withModuleFromAST' context ast moduleLLVMAssembly+ m <- withModuleFromLLVMAssembly' context s moduleAST+ m @?= ast,++ testCase "struct constant" $ do+ let s = "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \%0 = type { i32 }\n\+ \\n\+ \@0 = constant %0 { i32 1 }, align 4\n"+ ast = Module "<string>" "<string>" Nothing Nothing [+ TypeDefinition (UnName 0) (Just $ StructureType False [i32]),+ GlobalDefinition $ globalVariableDefaults {+ G.name = UnName 0,+ G.isConstant = True,+ G.type' = NamedTypeReference (UnName 0),+ G.initializer = Just $ C.Struct (Just $ UnName 0) False [ C.Int 32 1 ],+ G.alignment = 4+ }+ ]+ strCheck ast s+ ],+ + testGroup "failures" [+ testCase "bad block reference" $ withContext $ \context -> do+ let badAST = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.parameters = ([Parameter i32 (Name "x") []], False),+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ UnName 1 := Mul {+ nsw = True,+ nuw = False,+ operand0 = ConstantOperand (C.Int 32 1),+ operand1 = ConstantOperand (C.Int 32 1),+ metadata = []+ }+ ] (+ Do $ Br (Name "not here") []+ ),+ BasicBlock (Name "here") [+ ] (+ Do $ Ret (Just (LocalReference i32 (UnName 1))) []+ )+ ]+ }+ ]+ t <- runExceptT $ withModuleFromAST context badAST $ \_ -> return True+ t @?= Left "reference to undefined block: Name \"not here\"",++ testCase "multiple" $ withContext $ \context -> do+ let badAST = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ UnName 1 := Mul {+ nsw = False,+ nuw = False,+ operand0 = LocalReference i32 (Name "unknown"),+ operand1 = ConstantOperand (C.Int 32 1),+ metadata = []+ },+ UnName 2 := Mul {+ nsw = False,+ nuw = False,+ operand0 = LocalReference i32 (Name "unknown2"),+ operand1 = LocalReference i32 (UnName 1),+ metadata = []+ }+ ] (+ Do $ Ret (Just (LocalReference i32 (UnName 2))) []+ )+ ]+ }+ ]+ t <- runExceptT $ withModuleFromAST context badAST $ \_ -> return True+ t @?= Left "reference to undefined local: Name \"unknown\"",++ testCase "sourceFileName" $ withContext $ \context -> do+ let s = "; ModuleID = '<string>'\n\+ \source_filename = \"filename\"\n"+ ast = Module "<string>" "filename" Nothing Nothing []+ strCheck ast s+ ]+ ]
+ test/LLVM/Test/ObjectCode.hs view
@@ -0,0 +1,35 @@+module LLVM.Test.ObjectCode where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import qualified Data.ByteString as ByteString+import System.IO+import System.IO.Temp++import LLVM.Context+import LLVM.Module+import LLVM.Target++ll :: String+ll = unlines ["define i32 @main(i32 %argc, i8** %argv) {", " ret i32 0", "}"]++tests =+ testGroup+ "Object code serialization"+ [ testCase+ "serialization to ByteString and to file" $ do+ withContext $ \ctx ->+ withSystemTempFile "foo" $ \objFile handle -> do+ hClose handle+ failInIO $+ withHostTargetMachine $ \machine ->+ failInIO $+ withModuleFromLLVMAssembly ctx ll $ \mdl -> do+ obj <- failInIO $ moduleObject machine mdl+ _ <- failInIO $ writeObjectToFile machine (File objFile) mdl+ obj' <- ByteString.readFile objFile+ obj @=? obj'+ ]
+ test/LLVM/Test/Optimization.hs view
@@ -0,0 +1,306 @@+module LLVM.Test.Optimization where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import Data.Functor+import qualified Data.Set as Set+import qualified Data.Map as Map++import LLVM.Module+import LLVM.Context+import LLVM.PassManager+import qualified LLVM.Transforms as T+import LLVM.Target++import LLVM.AST as A+import LLVM.AST.Type as A.T+import LLVM.AST.Name+import LLVM.AST.AddrSpace+import LLVM.AST.DataLayout+import qualified LLVM.AST.IntegerPredicate as IPred+import qualified LLVM.AST.Linkage as L+import qualified LLVM.AST.Visibility as V+import qualified LLVM.AST.CallingConvention as CC+import qualified LLVM.AST.Attribute as A+import qualified LLVM.AST.Global as G+import qualified LLVM.AST.Constant as C++import qualified LLVM.Relocation as R+import qualified LLVM.CodeModel as CM+import qualified LLVM.CodeGenOpt as CGO++handAST = + Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.parameters = ([Parameter i32 (Name "x") []], False),+ G.functionAttributes = [Left (A.GroupID 0)],+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ UnName 1 := Mul {+ nsw = False,+ nuw = False,+ operand0 = ConstantOperand (C.Int 32 6),+ operand1 = ConstantOperand (C.Int 32 7),+ metadata = []+ }+ ] (+ Do $ Br (Name "here") []+ ),+ BasicBlock (Name "here") [+ Name "go" := ICmp {+ iPredicate = IPred.EQ,+ operand0 = LocalReference i32 (UnName 1),+ operand1 = ConstantOperand (C.Int 32 42),+ metadata = []+ }+ ] (+ Do $ CondBr {+ condition = LocalReference i1 (Name "go"),+ trueDest = Name "take",+ falseDest = Name "done",+ metadata' = []+ }+ ),+ BasicBlock (Name "take") [+ UnName 2 := Sub {+ nsw = False,+ nuw = False,+ operand0 = LocalReference i32 (Name "x"),+ operand1 = LocalReference i32 (Name "x"),+ metadata = []+ }+ ] (+ Do $ Br (Name "done") []+ ),+ BasicBlock (Name "done") [+ Name "r" := Phi {+ type' = i32,+ incomingValues = [+ (LocalReference i32 (UnName 2), Name "take"),+ (ConstantOperand (C.Int 32 57), Name "here")+ ],+ metadata = []+ }+ ] (+ Do $ Ret (Just (LocalReference i32 (Name "r"))) []+ )+ ]+ },+ FunctionAttributes (A.GroupID 0) [A.NoUnwind, A.ReadNone, A.UWTable]+ ]++isVectory :: A.Module -> Assertion+isVectory Module { moduleDefinitions = ds } =+ (@? "Module is not vectory") $ not $ null [ i + | GlobalDefinition (Function { G.basicBlocks = b }) <- ds,+ BasicBlock _ is _ <- b,+ _ := i@(ExtractElement {}) <- is+ ]++optimize :: PassSetSpec -> A.Module -> IO A.Module+optimize pss m = withContext $ \context -> withModuleFromAST' context m $ \mIn' -> do+ withPassManager pss $ \pm -> runPassManager pm mIn'+ moduleAST mIn'++tests = testGroup "Optimization" [+ testCase "curated" $ do+ mOut <- optimize defaultCuratedPassSetSpec handAST++ mOut @?= Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.parameters = ([Parameter i32 (Name "x") []], False),+ G.functionAttributes = [Left (A.GroupID 0)],+ G.basicBlocks = [+ BasicBlock (Name "here") [+ ] (+ Do $ Ret (Just (ConstantOperand (C.Int 32 0))) []+ )+ ]+ },+ FunctionAttributes (A.GroupID 0) [A.NoRecurse, A.NoUnwind, A.ReadNone, A.UWTable]+ ],++ testGroup "individual" [+ testCase "ConstantPropagation" $ do+ mOut <- optimize defaultPassSetSpec { transforms = [T.ConstantPropagation] } handAST++ mOut @?= Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.parameters = ([Parameter i32 (Name "x") []], False),+ G.functionAttributes = [Left (A.GroupID 0)],+ G.basicBlocks = [+ BasicBlock (UnName 0) [] (Do $ Br (Name "here") []),+ BasicBlock (Name "here") [] (+ Do $ CondBr {+ condition = ConstantOperand (C.Int 1 1),+ trueDest = Name "take", + falseDest = Name "done",+ metadata' = []+ }+ ),+ BasicBlock (Name "take") [+ UnName 1 := Sub {+ nsw = False,+ nuw = False,+ operand0 = LocalReference i32 (Name "x"),+ operand1 = LocalReference i32 (Name "x"),+ metadata = []+ }+ ] (+ Do $ Br (Name "done") []+ ),+ BasicBlock (Name "done") [+ Name "r" := Phi {+ type' = i32,+ incomingValues = [(LocalReference i32 (UnName 1), Name "take"),(ConstantOperand (C.Int 32 57), Name "here")],+ metadata = []+ }+ ] (+ Do $ Ret (Just (LocalReference i32 (Name "r"))) []+ )+ ]+ },+ FunctionAttributes (A.GroupID 0) [A.NoUnwind, A.ReadNone, A.UWTable]+ ],++ testCase "BasicBlockVectorization" $ do+ let+ mIn = Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = double,+ G.name = Name "foo",+ G.parameters = ([+ Parameter double (Name (l ++ n)) []+ | l <- [ "a", "b" ], n <- ["1", "2"]+ ], False),+ G.basicBlocks = [+ BasicBlock (UnName 0) ([+ Name (l ++ n) := op NoFastMathFlags (LocalReference double (Name (o1 ++ n))) (LocalReference double (Name (o2 ++ n))) []+ | (l, op, o1, o2) <- [+ ("x", FSub, "a", "b"),+ ("y", FMul, "x", "a"),+ ("z", FAdd, "y", "b")],+ n <- ["1", "2"]+ ] ++ [+ Name "r" := FMul NoFastMathFlags (LocalReference double (Name "z1")) (LocalReference double (Name "z2")) []+ ]) (Do $ Ret (Just (LocalReference double (Name "r"))) [])+ ]+ }+ ]+ mOut <- optimize (defaultPassSetSpec {+ transforms = [+ T.defaultVectorizeBasicBlocks { T.requiredChainDepth = 3 },+ T.InstructionCombining, + T.GlobalValueNumbering False+ ] }) mIn+ isVectory mOut,+ + testCase "LoopVectorize" $ do+ let+ mIn = + Module {+ moduleName = "<string>",+ moduleSourceFileName = "<string>",+ moduleDataLayout = Just $ (defaultDataLayout BigEndian) { + typeLayouts = Map.singleton (VectorAlign, 128) (AlignmentInfo 128 Nothing)+ },+ moduleTargetTriple = Just "x86_64",+ moduleDefinitions = [+ GlobalDefinition $ globalVariableDefaults {+ G.name = Name "a",+ G.linkage = L.Common,+ G.type' = A.T.ArrayType 2048 i32,+ G.initializer = Just (C.Null (A.T.ArrayType 2048 i32))+ },+ GlobalDefinition $ functionDefaults {+ G.returnType = A.T.void,+ G.name = Name "inc",+ G.functionAttributes = [Left (A.GroupID 0)],+ G.parameters = ([Parameter i32 (Name "n") []], False),+ G.basicBlocks = [+ BasicBlock (UnName 0) [+ UnName 1 := ICmp IPred.SGT (LocalReference i32 (Name "n")) (ConstantOperand (C.Int 32 0)) []+ ] (Do $ CondBr (LocalReference i1 (UnName 1)) (Name ".lr.ph") (Name "._crit_edge") []),+ BasicBlock (Name ".lr.ph") [+ Name "indvars.iv" := Phi i64 [ + (ConstantOperand (C.Int 64 0), UnName 0),+ (LocalReference i64 (Name "indvars.iv.next"), Name ".lr.ph")+ ] [],+ UnName 2 := GetElementPtr True (ConstantOperand (C.GlobalReference (A.T.ArrayType 2048 i32) (Name "a"))) [ + ConstantOperand (C.Int 64 0),+ (LocalReference i64 (Name "indvars.iv"))+ ] [],+ UnName 3 := Load False (LocalReference (ptr i32) (UnName 2)) Nothing 4 [],+ UnName 4 := Trunc (LocalReference i64 (Name "indvars.iv")) i32 [],+ UnName 5 := Add True False (LocalReference i32 (UnName 3)) (LocalReference i32 (UnName 4)) [],+ Do $ Store False (LocalReference (ptr i32) (UnName 2)) (LocalReference i32 (UnName 5)) Nothing 4 [],+ Name "indvars.iv.next" := Add False False (LocalReference i64 (Name "indvars.iv")) (ConstantOperand (C.Int 64 1)) [],+ Name "lftr.wideiv" := Trunc (LocalReference i64 (Name "indvars.iv.next")) i32 [],+ Name "exitcond" := ICmp IPred.EQ (LocalReference i32 (Name "lftr.wideiv")) (LocalReference i32 (Name "n")) []+ ] (Do $ CondBr (LocalReference i1 (Name "exitcond")) (Name "._crit_edge") (Name ".lr.ph") []),+ BasicBlock (Name "._crit_edge") [+ ] (Do $ Ret Nothing [])+ ]+ },+ FunctionAttributes (A.GroupID 0) [A.NoUnwind, A.ReadNone, A.UWTable, A.StackProtect]+ ]+ }+ mOut <- do+ let triple = "x86_64"+ (target, _) <- failInIO $ lookupTarget Nothing triple+ withTargetOptions $ \targetOptions -> do+ withTargetMachine target triple "" Map.empty targetOptions R.Default CM.Default CGO.Default $ \tm -> do+ optimize (defaultPassSetSpec { + transforms = [ T.defaultLoopVectorize ],+ dataLayout = moduleDataLayout mIn,+ targetMachine = Just tm+ }) mIn+ isVectory mOut,++ testCase "LowerInvoke" $ do+ -- This test doesn't test much about what LowerInvoke does, just that it seems to work.+ -- The pass seems to be quite deeply dependent on weakly documented presumptions about+ -- how unwinding works (as is the invoke instruction)+ withContext $ \context -> do+ withPassManager (defaultPassSetSpec { transforms = [T.LowerInvoke] }) $ \passManager -> do+ let astIn = + Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.parameters = ([Parameter i32 (Name "x") []], False),+ G.basicBlocks = [+ BasicBlock (Name "here") [+ ] (+ Do $ Ret (Just (ConstantOperand (C.Int 32 0))) []+ )+ ]+ }+ ] + astOut <- withModuleFromAST' context astIn $ \mIn -> do+ runPassManager passManager mIn+ moduleAST mIn+ astOut @?= Module "<string>" "<string>" Nothing Nothing [+ GlobalDefinition $ functionDefaults {+ G.returnType = i32,+ G.name = Name "foo",+ G.parameters = ([Parameter i32 (Name "x") []], False),+ G.basicBlocks = [+ BasicBlock (Name "here") [+ ] (+ Do $ Ret (Just (ConstantOperand (C.Int 32 0))) []+ )+ ]+ }+ ]+ ]+ ]
+ test/LLVM/Test/OrcJIT.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module LLVM.Test.OrcJIT where++import Test.Tasty+import Test.Tasty.HUnit++import LLVM.Test.Support++import Data.Foldable+import Data.IORef+import Data.Word+import Foreign.Ptr++import LLVM.Context+import LLVM.Module+import LLVM.OrcJIT+import LLVM.OrcJIT.IRCompileLayer (IRCompileLayer, withIRCompileLayer)+import qualified LLVM.OrcJIT.IRCompileLayer as IRCompileLayer+import LLVM.OrcJIT.CompileOnDemandLayer (CompileOnDemandLayer, withIndirectStubsManagerBuilder, withJITCompileCallbackManager, withCompileOnDemandLayer)+import qualified LLVM.OrcJIT.CompileOnDemandLayer as CODLayer+import LLVM.Target++testModule :: String+testModule =+ "; ModuleID = '<string>'\n\+ \source_filename = \"<string>\"\n\+ \\n\+ \declare i32 @testFunc()\n\+ \define i32 @main(i32, i8**) {\n\+ \ %3 = call i32 @testFunc()\n\+ \ ret i32 %3\n\+ \}\n"++withTestModule :: (Module -> IO a) -> IO a+withTestModule f = withContext $ \context -> withModuleFromLLVMAssembly' context testModule f++myTestFuncImpl :: IO Word32+myTestFuncImpl = return 42++foreign import ccall "wrapper"+ wrapTestFunc :: IO Word32 -> IO (FunPtr (IO Word32))++foreign import ccall "dynamic"+ mkMain :: FunPtr (IO Word32) -> IO Word32++nullResolver :: MangledSymbol -> IO JITSymbol+nullResolver s = putStrLn "nullresolver" >> return (JITSymbol 0 (JITSymbolFlags False False))++resolver :: MangledSymbol -> IRCompileLayer -> MangledSymbol -> IO JITSymbol+resolver testFunc compileLayer symbol+ | symbol == testFunc = do+ funPtr <- wrapTestFunc myTestFuncImpl+ let addr = ptrToWordPtr (castFunPtrToPtr funPtr)+ return (JITSymbol addr (JITSymbolFlags False True))+ | otherwise = IRCompileLayer.findSymbol compileLayer symbol True++codResolver :: MangledSymbol -> CompileOnDemandLayer -> MangledSymbol -> IO JITSymbol+codResolver testFunc compileLayer symbol+ | symbol == testFunc = do+ funPtr <- wrapTestFunc myTestFuncImpl+ let addr = ptrToWordPtr (castFunPtrToPtr funPtr)+ return (JITSymbol addr (JITSymbolFlags False True))+ | otherwise = CODLayer.findSymbol compileLayer symbol True++tests :: TestTree+tests =+ testGroup "OrcJit" [+ testCase "eager compilation" $ do+ withTestModule $ \mod ->+ failInIO $ withHostTargetMachine $ \tm ->+ withObjectLinkingLayer $ \objectLayer ->+ withIRCompileLayer objectLayer tm $ \compileLayer -> do+ testFunc <- IRCompileLayer.mangleSymbol compileLayer "testFunc"+ IRCompileLayer.withModuleSet+ compileLayer+ [mod]+ (SymbolResolver (resolver testFunc compileLayer) nullResolver) $+ \moduleSet -> do+ mainSymbol <- IRCompileLayer.mangleSymbol compileLayer "main"+ JITSymbol mainFn _ <- IRCompileLayer.findSymbol compileLayer mainSymbol True+ result <- mkMain (castPtrToFunPtr (wordPtrToPtr mainFn))+ result @?= 42,++ testCase "lazy compilation" $ do+ withTestModule $ \mod ->+ failInIO $ withHostTargetMachine $ \tm -> do+ triple <- getTargetMachineTriple tm+ withObjectLinkingLayer $ \objectLayer ->+ withIRCompileLayer objectLayer tm $ \baseLayer ->+ withIndirectStubsManagerBuilder triple $ \stubsMgr ->+ withJITCompileCallbackManager triple Nothing $ \callbackMgr ->+ withCompileOnDemandLayer baseLayer (\x -> return [x]) callbackMgr stubsMgr False $ \compileLayer -> do+ testFunc <- CODLayer.mangleSymbol compileLayer "testFunc"+ CODLayer.withModuleSet+ compileLayer+ [mod]+ (SymbolResolver (codResolver testFunc compileLayer) nullResolver) $+ \moduleSet -> do+ mainSymbol <- CODLayer.mangleSymbol compileLayer "main"+ JITSymbol mainFn _ <- CODLayer.findSymbol compileLayer mainSymbol True+ result <- mkMain (castPtrToFunPtr (wordPtrToPtr mainFn))+ result @?= 42+ ]
+ test/LLVM/Test/Support.hs view
@@ -0,0 +1,42 @@+module LLVM.Test.Support where++import Test.Tasty+import Test.Tasty.HUnit++import Data.Functor+import Control.Monad+import Control.Monad.Trans.Except+import Text.Show.Pretty++import LLVM.Context+import LLVM.Module+import LLVM.Diagnostic++class FailInIO f where+ errorToString :: f -> String++failInIO :: FailInIO f => ExceptT f IO a -> IO a+failInIO = either (fail . errorToString) return <=< runExceptT++instance FailInIO String where+ errorToString = id++instance FailInIO (Either String Diagnostic) where+ errorToString = either id diagnosticDisplay++withModuleFromLLVMAssembly' c s f = failInIO $ withModuleFromLLVMAssembly c s f+withModuleFromAST' c a f = failInIO $ withModuleFromAST c a f+withModuleFromBitcode' c a f = failInIO $ withModuleFromBitcode c ("<string>", a) f++assertEqPretty :: (Eq a, Show a) => a -> a -> Assertion+assertEqPretty actual expected = do+ assertBool+ ("expected: " ++ ppShow expected ++ "\n" ++ "but got: " ++ ppShow actual ++ "\n")+ (expected == actual)++strCheckC mAST mStr mStrCanon = withContext $ \context -> do+ a <- withModuleFromLLVMAssembly' context mStr moduleAST+ s <- withModuleFromAST' context mAST moduleLLVMAssembly+ (a,s) `assertEqPretty` (mAST, mStrCanon)++strCheck mAST mStr = strCheckC mAST mStr mStr
+ test/LLVM/Test/Target.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE+ RecordWildCards+ #-}+module LLVM.Test.Target where++import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck+import Test.QuickCheck+import Test.QuickCheck.Property++import Control.Monad++import LLVM.Target+import LLVM.Target.Options+import LLVM.Target.LibraryFunction++instance Arbitrary FloatABI where+ arbitrary = elements [minBound .. maxBound]++instance Arbitrary FloatingPointOperationFusionMode where+ arbitrary = elements [minBound .. maxBound]++instance Arbitrary Options where+ arbitrary = do+ printMachineCode <- arbitrary+ lessPreciseFloatingPointMultiplyAddOption <- arbitrary+ unsafeFloatingPointMath <- arbitrary+ noInfinitiesFloatingPointMath <- arbitrary+ noNaNsFloatingPointMath <- arbitrary+ honorSignDependentRoundingFloatingPointMathOption <- arbitrary+ noZerosInBSS <- arbitrary+ guaranteedTailCallOptimization <- arbitrary+ enableFastInstructionSelection <- arbitrary+ useInitArray <- arbitrary+ disableIntegratedAssembler <- arbitrary+ compressDebugSections <- arbitrary+ trapUnreachable <- arbitrary+ stackAlignmentOverride <- arbitrary+ floatABIType <- arbitrary+ allowFloatingPointOperationFusion <- arbitrary+ return Options { .. }++tests = testGroup "Target" [+ testGroup "Options" [+ testProperty "basic" $ \options -> ioProperty $ do+ withTargetOptions $ \to -> do+ pokeTargetOptions options to+ options' <- peekTargetOptions to+ return $ options == options'+ ],+ testGroup "LibraryFunction" [+ testGroup "set-get" [+ testCase (show lf) $ do+ triple <- getDefaultTargetTriple+ withTargetLibraryInfo triple $ \tli -> do+ setLibraryFunctionAvailableWithName tli lf "foo"+ nm <- getLibraryFunctionName tli lf+ nm @?= "foo"+ | lf <- [minBound, maxBound]+ ],+ testCase "get" $ do+ triple <- getDefaultTargetTriple+ withTargetLibraryInfo triple $ \tli -> do+ lf <- getLibraryFunction tli "printf"+ lf @?= Just LF__printf+ ],+ testCase "Host" $ do+ features <- getHostCPUFeatures+ return ()+ ]
+ test/LLVM/Test/Tests.hs view
@@ -0,0 +1,39 @@+module LLVM.Test.Tests where++import Test.Tasty++import qualified LLVM.Test.Analysis as Analysis+import qualified LLVM.Test.CallingConvention as CallingConvention+import qualified LLVM.Test.Constants as Constants+import qualified LLVM.Test.DataLayout as DataLayout+import qualified LLVM.Test.ExecutionEngine as ExecutionEngine+import qualified LLVM.Test.Global as Global+import qualified LLVM.Test.InlineAssembly as InlineAssembly+import qualified LLVM.Test.Instructions as Instructions+import qualified LLVM.Test.Instrumentation as Instrumentation+import qualified LLVM.Test.Linking as Linking+import qualified LLVM.Test.Metadata as Metadata+import qualified LLVM.Test.Module as Module+import qualified LLVM.Test.ObjectCode as ObjectCode+import qualified LLVM.Test.Optimization as Optimization+import qualified LLVM.Test.OrcJIT as OrcJIT+import qualified LLVM.Test.Target as Target++tests = testGroup "llvm-hs" [+ CallingConvention.tests,+ Constants.tests,+ DataLayout.tests,+ ExecutionEngine.tests,+ Global.tests,+ InlineAssembly.tests,+ Instructions.tests,+ Metadata.tests,+ Module.tests,+ OrcJIT.tests,+ Optimization.tests,+ Target.tests,+ Analysis.tests,+ Linking.tests,+ Instrumentation.tests,+ ObjectCode.tests+ ]
+ test/Test.hs view
@@ -0,0 +1,10 @@+import Test.Tasty+import qualified LLVM.Test.Tests as LLVM+import LLVM.CommandLine++main = do+ parseCommandLineOptions [+ "test",+ "-bb-vectorize-ignore-target-info"+ ] Nothing+ defaultMain LLVM.tests