llvm-analysis-0.3.0: tests/AndersenTest.hs
{-# LANGUAGE CPP #-}
module Main ( main ) where
import Data.Map ( Map )
import Data.Set ( Set )
import qualified Data.Map as M
import qualified Data.Set as S
import Data.Monoid
import System.Environment ( getArgs, withArgs )
import System.FilePath
import Test.HUnit ( assertEqual )
import LLVM.Analysis
-- import LLVM.Analysis.PointsTo.AllocatorProfile
import LLVM.Analysis.PointsTo.Andersen
import LLVM.Analysis.PointsTo
import LLVM.Analysis.Util.Testing
import LLVM.Parse
#if defined(DEBUGGRAPH)
import Data.GraphViz
import System.IO.Unsafe ( unsafePerformIO )
viewConstraintGraph :: a -> Andersen -> a
viewConstraintGraph v a = unsafePerformIO $ do
let dg = andersenConstraintGraph a
runGraphvizCanvas' dg Gtk
return v
#else
viewConstraintGraph :: a -> Andersen -> a
viewConstraintGraph = const
#endif
extractSummary :: Module -> Map String (Set String)
extractSummary m =
foldr addInfo mempty ptrs `viewConstraintGraph` pta
where
pta = runPointsToAnalysis m
ptrs = map toValue (globalPointerVariables m) ++ formals -- ++ map Value (functionPointerParameters m)
formals = concatMap (map toValue . functionParameters) (moduleDefinedFunctions m)
addInfo v r =
let vals = pointsTo pta v
name = maybe "???" show (valueName v)
in case null vals of
True -> r
False ->
let targets = map (maybe "??" show . valueName) vals -- `debug` show vals
in M.insert name (S.fromList targets) r
isPointerType t = case t of
TypePointer _ _ -> True
_ -> False
isPointer :: (IsValue a) => a -> Bool
isPointer = isPointerType . valueType
globalPointerVariables :: Module -> [GlobalVariable]
globalPointerVariables m = filter isPointer (moduleGlobalVariables m)
functionPointerParameters :: Module -> [Argument]
functionPointerParameters m = concatMap pointerParams (moduleDefinedFunctions m)
where
pointerParams = filter isPointer . functionParameters
main :: IO ()
main = do
args <- getArgs
let pattern = case args of
[] -> "tests/points-to-inputs/*/*.c"
[infile] -> infile
_ -> error "Only one argument allowed"
testDescriptors = [ TestDescriptor { testPattern = pattern
, testExpectedMapping = expectedMapper
, testResultBuilder = extractSummary
, testResultComparator = assertEqual
}
]
withArgs [] $ testAgainstExpected opts parser testDescriptors
where
-- These optimizations aren't really necessary (the algorithm
-- works fine with unoptimized bitcode), but comparing the results
-- visually is much easier with the optimized version.
opts = [ "-mem2reg", "-basicaa", "-gvn" ]
parser = parseLLVMFile defaultParserOptions
expectedMapper = (<.> "expected-andersen")