content: module TestFunctions
    (
      functionTests
    )
  where
  
  import qualified Data.Map.Strict as Map
  
  import qualified Test.Tasty as T
  import           Test.Tasty.HUnit ( testCase, (@=?) )
  
  import qualified Text.LLVM.AST as L
  
  import qualified Lang.Crucible.LLVM.MemModel as LLVMMem
  
  import MemSetup ( withInitializedMemory )
  
  
  functionTests :: T.TestTree
  functionTests =
    T.testGroup "Functions" $
  
    -- The following ensures that Crucible treats aliases to functions properly
  
    let alias = L.GlobalAlias
                { L.aliasLinkage = Nothing
                , L.aliasVisibility = Nothing
                , L.aliasName = L.Symbol "aliasName"
                , L.aliasType =
                    L.FunTy
                    (L.PrimType L.Void)
                    [ L.PtrTo (L.Alias (L.Ident "class.std::cls")) ]
                    False
                , L.aliasTarget =
                    L.ValSymbol (L.Symbol "defName")
                }
  
        def = L.Define
              { L.defLinkage = Just L.WeakODR
              , L.defVisibility = Nothing
              , L.defRetType = L.PrimType L.Void
              , L.defName = L.Symbol "defName"
              , L.defArgs =
                  [ L.Typed
                    { L.typedType = L.PtrTo (L.Alias (L.Ident "class.std::cls"))
                    , L.typedValue = L.Ident "0"
                    }
                  ]
              , L.defVarArgs = False
              , L.defAttrs = []
              , L.defSection = Nothing
              , L.defGC = Nothing
              , L.defBody =
                  [ L.BasicBlock
                    { L.bbLabel = Just (L.Anon 1)
                    , L.bbStmts =
                        [ L.Result
                          (L.Ident "2")
                          (L.Alloca
                            (L.PtrTo
                              (L.Alias (L.Ident "class.std::cls"))) Nothing (Just 8))
                          []
                        , L.Effect L.RetVoid []
                        ]
                    }
                  ]
              , L.defMetadata = mempty
              , L.defComdat = Nothing
              }
    in [ testCase "initializeMemory (functions)" $
         let mod'    = L.emptyModule { L.modDefines = [def]
                                     , L.modAliases = [alias]
                                     }
             inMap k = (Just () @=?) . fmap (const ()) . Map.lookup k
         in withInitializedMemory mod' $ \memImpl ->
           inMap
           (L.Symbol "aliasName")
           (LLVMMem.memImplGlobalMap memImpl)
       ]
  