-- |
-- Module           : Lang.Crucible.LLVM.Intrinsics.Libcxx
-- Description      : Override definitions for C++ standard library functions
-- Copyright        : (c) Galois, Inc 2015-2019
-- License          : BSD3
-- Maintainer       : Rob Dockins <rdockins@galois.com>
-- Stability        : provisional
------------------------------------------------------------------------

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DoAndIfThenElse #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ImpredicativeTypes #-}
{-# LANGUAGE ImplicitParams #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}

module Lang.Crucible.LLVM.Intrinsics.Libcxx
  ( register_cpp_override
    -- ** iostream
  , putToOverride12
  , putToOverride9
  , endlOverride
  , sentryOverride
  , sentryBoolOverride
  ) where

import qualified ABI.Itanium as ABI
import           Control.Applicative (empty)
import           Control.Lens ((^.))
import           Control.Monad.Reader
import           Data.List (isInfixOf)
import           Data.Type.Equality ((:~:)(Refl), testEquality)
import qualified Text.LLVM.AST as L

import qualified Data.BitVector.Sized as BV
import qualified Data.Parameterized.Context as Ctx
import           Data.Parameterized.NatRepr (knownNat)

import           What4.Interface (bvLit, natLit)

import           Lang.Crucible.Backend
import           Lang.Crucible.CFG.Common (GlobalVar)
import           Lang.Crucible.Simulator.RegMap (RegValue, regValue)
import           Lang.Crucible.Panic (panic)
import           Lang.Crucible.Types (TypeRepr(UnitRepr), CtxRepr)

import           Lang.Crucible.LLVM.Extension
import           Lang.Crucible.LLVM.Intrinsics.Common
import           Lang.Crucible.LLVM.MemModel
import           Lang.Crucible.LLVM.Translation.Monad
import           Lang.Crucible.LLVM.Translation.Types

------------------------------------------------------------------------
-- ** General

-- | C++ overrides generally have a bit more work to do: their types are more
-- complex, their names are mangled in the LLVM module, it's a big mess.
register_cpp_override ::
  (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) =>
  SomeCPPOverride p sym arch ->
  OverrideTemplate p sym arch rtp l a
register_cpp_override :: forall sym (wptr :: Natural) p (arch :: LLVMArch) rtp
       (l :: Ctx CrucibleType) (a :: CrucibleType).
(IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) =>
SomeCPPOverride p sym arch -> OverrideTemplate p sym arch rtp l a
register_cpp_override SomeCPPOverride p sym arch
someCPPOverride =
  TemplateMatcher
-> RegOverrideM p sym arch rtp l a ()
-> OverrideTemplate p sym arch rtp l a
forall p sym (arch :: LLVMArch) rtp (l :: Ctx CrucibleType)
       (a :: CrucibleType).
TemplateMatcher
-> RegOverrideM p sym arch rtp l a ()
-> OverrideTemplate p sym arch rtp l a
OverrideTemplate ([String] -> TemplateMatcher
SubstringsMatch (String
"_Z" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: SomeCPPOverride p sym arch -> [String]
forall p sym (arch :: LLVMArch).
SomeCPPOverride p sym arch -> [String]
cppOverrideSubstrings SomeCPPOverride p sym arch
someCPPOverride)) (RegOverrideM p sym arch rtp l a ()
 -> OverrideTemplate p sym arch rtp l a)
-> RegOverrideM p sym arch rtp l a ()
-> OverrideTemplate p sym arch rtp l a
forall a b. (a -> b) -> a -> b
$
  do (Declare
requestedDecl, Maybe DecodedName
decName, LLVMContext arch
llvmctx) <- ReaderT
  (Declare, Maybe DecodedName, LLVMContext arch)
  (MaybeT (OverrideSim p sym LLVM rtp l a))
  (Declare, Maybe DecodedName, LLVMContext arch)
forall r (m :: Type -> Type). MonadReader r m => m r
ask
     case Maybe DecodedName
decName of
       Maybe DecodedName
Nothing -> RegOverrideM p sym arch rtp l a ()
forall a.
ReaderT
  (Declare, Maybe DecodedName, LLVMContext arch)
  (MaybeT (OverrideSim p sym LLVM rtp l a))
  a
forall (f :: Type -> Type) a. Alternative f => f a
empty
       Just DecodedName
nm ->
         case SomeCPPOverride p sym arch
-> Declare
-> DecodedName
-> LLVMContext arch
-> Maybe (SomeLLVMOverride p sym)
forall p sym (arch :: LLVMArch).
SomeCPPOverride p sym arch
-> Declare
-> DecodedName
-> LLVMContext arch
-> Maybe (SomeLLVMOverride p sym)
cppOverrideAction SomeCPPOverride p sym arch
someCPPOverride Declare
requestedDecl DecodedName
nm LLVMContext arch
llvmctx of
           Maybe (SomeLLVMOverride p sym)
Nothing -> RegOverrideM p sym arch rtp l a ()
forall a.
ReaderT
  (Declare, Maybe DecodedName, LLVMContext arch)
  (MaybeT (OverrideSim p sym LLVM rtp l a))
  a
forall (f :: Type -> Type) a. Alternative f => f a
empty
           Just (SomeLLVMOverride LLVMOverride p sym args ret
override) -> LLVMOverride p sym args ret -> RegOverrideM p sym arch rtp l a ()
forall p (args :: Ctx CrucibleType) (ret :: CrucibleType) sym
       (arch :: LLVMArch) (wptr :: Natural) (l :: Ctx CrucibleType)
       (a :: CrucibleType) rtp.
(IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym) =>
LLVMOverride p sym args ret -> RegOverrideM p sym arch rtp l a ()
register_llvm_override LLVMOverride p sym args ret
override


-- type CPPOverride p sym arch args ret =
--   L.Declare -> LLVMContext arch -> Maybe (LLVMOverride p sym arch args ret)

-- | We can only tell whether we should install a C++ override after demangling
--  the function name, which is expensive. As a first approximation, we ask whether
--  the function's name contains a few substrings, in order.
data SomeCPPOverride p sym arch =
  SomeCPPOverride
  { forall p sym (arch :: LLVMArch).
SomeCPPOverride p sym arch -> [String]
cppOverrideSubstrings :: [String]
  , forall p sym (arch :: LLVMArch).
SomeCPPOverride p sym arch
-> Declare
-> DecodedName
-> LLVMContext arch
-> Maybe (SomeLLVMOverride p sym)
cppOverrideAction :: L.Declare -> ABI.DecodedName -> LLVMContext arch -> Maybe (SomeLLVMOverride p sym)
  }

------------------------------------------------------------------------
-- ** No-ops

------------------------------------------------------------------------
-- *** Utilities

matchSymbolName :: (L.Symbol -> ABI.DecodedName -> Bool)
                -> L.Declare
                -> ABI.DecodedName
                -> Maybe a
                -> Maybe a
matchSymbolName :: forall a.
(Symbol -> DecodedName -> Bool)
-> Declare -> DecodedName -> Maybe a -> Maybe a
matchSymbolName Symbol -> DecodedName -> Bool
match Declare
decl DecodedName
decodedName =
  if Bool -> Bool
not (Symbol -> DecodedName -> Bool
match (Declare -> Symbol
L.decName Declare
decl) DecodedName
decodedName)
  then Maybe a -> Maybe a -> Maybe a
forall a b. a -> b -> a
const Maybe a
forall a. Maybe a
Nothing
  else Maybe a -> Maybe a
forall a. a -> a
id

panic_ :: (Show a, Show b)
       => String
       -> L.Declare
       -> a
       -> b
       -> c
panic_ :: forall a b c. (Show a, Show b) => String -> Declare -> a -> b -> c
panic_ String
from Declare
decl a
args b
ret =
  String -> [String] -> c
forall a. HasCallStack => String -> [String] -> a
panic String
from [ String
"Ill-typed override"
             , String
"Name: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
nm
             , String
"Args: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
args
             , String
"Ret:  " String -> String -> String
forall a. [a] -> [a] -> [a]
++ b -> String
forall a. Show a => a -> String
show b
ret
             ]
  where L.Symbol String
nm = Declare -> Symbol
L.decName Declare
decl

-- | If the requested declaration's symbol matches the filter, look up its
-- function handle in the symbol table and use that to construct an override
mkOverride :: (IsSymInterface sym, HasPtrWidth (ArchWidth arch))
           => [String] -- ^ Substrings for name filtering
           -> (forall args ret. L.Declare -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
           -> (L.Symbol -> ABI.DecodedName -> Bool)
           -> SomeCPPOverride p sym arch
mkOverride :: forall sym (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth (ArchWidth arch)) =>
[String]
-> (forall (args :: Ctx CrucibleType) (ret :: CrucibleType).
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
mkOverride [String]
substrings forall (args :: Ctx CrucibleType) (ret :: CrucibleType).
Declare
-> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym)
ov Symbol -> DecodedName -> Bool
filt =
  [String]
-> (Declare
    -> DecodedName
    -> LLVMContext arch
    -> Maybe (SomeLLVMOverride p sym))
-> SomeCPPOverride p sym arch
forall p sym (arch :: LLVMArch).
[String]
-> (Declare
    -> DecodedName
    -> LLVMContext arch
    -> Maybe (SomeLLVMOverride p sym))
-> SomeCPPOverride p sym arch
SomeCPPOverride [String]
substrings ((Declare
  -> DecodedName
  -> LLVMContext arch
  -> Maybe (SomeLLVMOverride p sym))
 -> SomeCPPOverride p sym arch)
-> (Declare
    -> DecodedName
    -> LLVMContext arch
    -> Maybe (SomeLLVMOverride p sym))
-> SomeCPPOverride p sym arch
forall a b. (a -> b) -> a -> b
$ \Declare
requestedDecl DecodedName
decodedName LLVMContext arch
llvmctx ->
    let ?lc = LLVMContext arch
llvmctxLLVMContext arch
-> Getting TypeContext (LLVMContext arch) TypeContext
-> TypeContext
forall s a. s -> Getting a s a -> a
^.Getting TypeContext (LLVMContext arch) TypeContext
forall (arch :: LLVMArch) (f :: Type -> Type).
Functor f =>
(TypeContext -> f TypeContext)
-> LLVMContext arch -> f (LLVMContext arch)
llvmTypeCtx in
    (Symbol -> DecodedName -> Bool)
-> Declare
-> DecodedName
-> Maybe (SomeLLVMOverride p sym)
-> Maybe (SomeLLVMOverride p sym)
forall a.
(Symbol -> DecodedName -> Bool)
-> Declare -> DecodedName -> Maybe a -> Maybe a
matchSymbolName Symbol -> DecodedName -> Bool
filt Declare
requestedDecl DecodedName
decodedName (Maybe (SomeLLVMOverride p sym) -> Maybe (SomeLLVMOverride p sym))
-> Maybe (SomeLLVMOverride p sym) -> Maybe (SomeLLVMOverride p sym)
forall a b. (a -> b) -> a -> b
$
      Declare
-> (forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
    CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> Maybe (SomeLLVMOverride p sym)
forall (wptr :: Natural) (m :: Type -> Type) a.
(?lc::TypeContext, HasPtrWidth wptr, MonadFail m) =>
Declare
-> (forall (args :: Ctx CrucibleType) (ret :: CrucibleType).
    CtxRepr args -> TypeRepr ret -> m a)
-> m a
llvmDeclToFunHandleRepr' Declare
requestedDecl ((forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
  CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
 -> Maybe (SomeLLVMOverride p sym))
-> (forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
    CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> Maybe (SomeLLVMOverride p sym)
forall a b. (a -> b) -> a -> b
$ \CtxRepr args
argTys TypeRepr ret
retTy ->
        Declare
-> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym)
forall (args :: Ctx CrucibleType) (ret :: CrucibleType).
Declare
-> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym)
ov Declare
requestedDecl CtxRepr args
argTys TypeRepr ret
retTy

------------------------------------------------------------------------
-- *** No-op override builders

-- | Make an override for a function which doesn't return anything.
voidOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch)
             => [String]
             -> (L.Symbol -> ABI.DecodedName -> Bool)
             -> SomeCPPOverride p sym arch
voidOverride :: forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
[String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
voidOverride [String]
substrings =
  [String]
-> (forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
forall sym (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth (ArchWidth arch)) =>
[String]
-> (forall (args :: Ctx CrucibleType) (ret :: CrucibleType).
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
mkOverride [String]
substrings ((forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
  Declare
  -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
 -> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch)
-> (forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
forall a b. (a -> b) -> a -> b
$ \Declare
decl CtxRepr args
argTys TypeRepr ret
retTy -> SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym)
forall a. a -> Maybe a
Just (SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym))
-> SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym)
forall a b. (a -> b) -> a -> b
$
      case TypeRepr ret
retTy of
        TypeRepr ret
UnitRepr -> LLVMOverride p sym args ret -> SomeLLVMOverride p sym
forall p sym (args :: Ctx CrucibleType) (ret :: CrucibleType).
LLVMOverride p sym args ret -> SomeLLVMOverride p sym
SomeLLVMOverride (LLVMOverride p sym args ret -> SomeLLVMOverride p sym)
-> LLVMOverride p sym args ret -> SomeLLVMOverride p sym
forall a b. (a -> b) -> a -> b
$ Declare
-> CtxRepr args
-> TypeRepr ret
-> (forall {bak}.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
forall p sym (args :: Ctx CrucibleType) (ret :: CrucibleType).
Declare
-> CtxRepr args
-> TypeRepr ret
-> (forall bak.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall rtp (args' :: Ctx CrucibleType) (ret' :: CrucibleType).
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
LLVMOverride Declare
decl CtxRepr args
argTys TypeRepr ret
retTy ((forall {bak}.
  IsSymBackend sym bak =>
  GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
  -> bak
  -> Assignment (RegEntry sym) args
  -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
     OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
 -> LLVMOverride p sym args ret)
-> (forall {bak}.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
forall a b. (a -> b) -> a -> b
$ \GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
_mem bak
_sym Assignment (RegEntry sym) args
_args -> () -> OverrideSim p sym LLVM rtp args' ret' ()
forall a. a -> OverrideSim p sym LLVM rtp args' ret' a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure ()
        TypeRepr ret
_ -> String
-> Declare
-> CtxRepr args
-> TypeRepr ret
-> SomeLLVMOverride p sym
forall a b c. (Show a, Show b) => String -> Declare -> a -> b -> c
panic_ String
"voidOverride" Declare
decl CtxRepr args
argTys TypeRepr ret
retTy

-- | Make an override for a function of (LLVM) type @a -> a@, for any @a@.
--
-- The override simply returns its input.
identityOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch)
                 => [String]
                 -> (L.Symbol -> ABI.DecodedName -> Bool)
                 -> SomeCPPOverride p sym arch
identityOverride :: forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
[String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
identityOverride [String]
substrings =
  [String]
-> (forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
forall sym (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth (ArchWidth arch)) =>
[String]
-> (forall (args :: Ctx CrucibleType) (ret :: CrucibleType).
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
mkOverride [String]
substrings ((forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
  Declare
  -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
 -> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch)
-> (forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
forall a b. (a -> b) -> a -> b
$ \Declare
decl CtxRepr args
argTys TypeRepr ret
retTy -> SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym)
forall a. a -> Maybe a
Just (SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym))
-> SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym)
forall a b. (a -> b) -> a -> b
$
    case CtxRepr args
argTys of
      (Assignment TypeRepr ctx
Ctx.Empty Ctx.:> TypeRepr tp
argTy)
        | Just tp :~: ret
Refl <- TypeRepr tp -> TypeRepr ret -> Maybe (tp :~: ret)
forall {k} (f :: k -> Type) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
forall (a :: CrucibleType) (b :: CrucibleType).
TypeRepr a -> TypeRepr b -> Maybe (a :~: b)
testEquality TypeRepr tp
argTy TypeRepr ret
retTy ->
            LLVMOverride p sym args ret -> SomeLLVMOverride p sym
forall p sym (args :: Ctx CrucibleType) (ret :: CrucibleType).
LLVMOverride p sym args ret -> SomeLLVMOverride p sym
SomeLLVMOverride (LLVMOverride p sym args ret -> SomeLLVMOverride p sym)
-> LLVMOverride p sym args ret -> SomeLLVMOverride p sym
forall a b. (a -> b) -> a -> b
$ Declare
-> CtxRepr args
-> TypeRepr ret
-> (forall {bak}.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
forall p sym (args :: Ctx CrucibleType) (ret :: CrucibleType).
Declare
-> CtxRepr args
-> TypeRepr ret
-> (forall bak.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall rtp (args' :: Ctx CrucibleType) (ret' :: CrucibleType).
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
LLVMOverride Declare
decl CtxRepr args
argTys TypeRepr ret
retTy ((forall {bak}.
  IsSymBackend sym bak =>
  GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
  -> bak
  -> Assignment (RegEntry sym) args
  -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
     OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
 -> LLVMOverride p sym args ret)
-> (forall {bak}.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
forall a b. (a -> b) -> a -> b
$ \GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
_mem bak
_sym Assignment (RegEntry sym) args
args ->
              -- Just return the input
              RegValue sym ret
-> OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret)
forall a. a -> OverrideSim p sym LLVM rtp args' ret' a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (CurryAssignment args (RegEntry sym) (RegValue sym ret)
-> Assignment (RegEntry sym) args -> RegValue sym ret
forall k (ctx :: Ctx k) (f :: k -> Type) x.
CurryAssignmentClass ctx =>
CurryAssignment ctx f x -> Assignment f ctx -> x
forall (f :: CrucibleType -> Type) x.
CurryAssignment args f x -> Assignment f args -> x
Ctx.uncurryAssignment CurryAssignment args (RegEntry sym) (RegValue sym ret)
RegEntry sym ret -> RegValue sym ret
forall sym (tp :: CrucibleType). RegEntry sym tp -> RegValue sym tp
regValue Assignment (RegEntry sym) args
args)

      CtxRepr args
_ -> String
-> Declare
-> CtxRepr args
-> TypeRepr ret
-> SomeLLVMOverride p sym
forall a b c. (Show a, Show b) => String -> Declare -> a -> b -> c
panic_ String
"identityOverride" Declare
decl CtxRepr args
argTys TypeRepr ret
retTy

-- | Make an override for a function of (LLVM) type @a -> b -> a@, for any @a@.
--
-- The override simply returns its first input.
constOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch)
              => [String]
              -> (L.Symbol -> ABI.DecodedName -> Bool)
              -> SomeCPPOverride p sym arch
constOverride :: forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
[String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
constOverride [String]
substrings =
  [String]
-> (forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
forall sym (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth (ArchWidth arch)) =>
[String]
-> (forall (args :: Ctx CrucibleType) (ret :: CrucibleType).
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
mkOverride [String]
substrings ((forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
  Declare
  -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
 -> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch)
-> (forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
forall a b. (a -> b) -> a -> b
$ \Declare
decl CtxRepr args
argTys TypeRepr ret
retTy -> SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym)
forall a. a -> Maybe a
Just (SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym))
-> SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym)
forall a b. (a -> b) -> a -> b
$
    case CtxRepr args
argTys of
      (Assignment TypeRepr ctx
Ctx.Empty Ctx.:> TypeRepr tp
fstTy Ctx.:> TypeRepr tp
_)
        | Just tp :~: ret
Refl <- TypeRepr tp -> TypeRepr ret -> Maybe (tp :~: ret)
forall {k} (f :: k -> Type) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
forall (a :: CrucibleType) (b :: CrucibleType).
TypeRepr a -> TypeRepr b -> Maybe (a :~: b)
testEquality TypeRepr tp
fstTy TypeRepr ret
retTy ->
        LLVMOverride p sym args ret -> SomeLLVMOverride p sym
forall p sym (args :: Ctx CrucibleType) (ret :: CrucibleType).
LLVMOverride p sym args ret -> SomeLLVMOverride p sym
SomeLLVMOverride (LLVMOverride p sym args ret -> SomeLLVMOverride p sym)
-> LLVMOverride p sym args ret -> SomeLLVMOverride p sym
forall a b. (a -> b) -> a -> b
$ Declare
-> CtxRepr args
-> TypeRepr ret
-> (forall {bak}.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
forall p sym (args :: Ctx CrucibleType) (ret :: CrucibleType).
Declare
-> CtxRepr args
-> TypeRepr ret
-> (forall bak.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall rtp (args' :: Ctx CrucibleType) (ret' :: CrucibleType).
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
LLVMOverride Declare
decl CtxRepr args
argTys TypeRepr ret
retTy ((forall {bak}.
  IsSymBackend sym bak =>
  GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
  -> bak
  -> Assignment (RegEntry sym) args
  -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
     OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
 -> LLVMOverride p sym args ret)
-> (forall {bak}.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
forall a b. (a -> b) -> a -> b
$ \GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
_mem bak
_sym Assignment (RegEntry sym) args
args ->
          RegValue sym ret
-> OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret)
forall a. a -> OverrideSim p sym LLVM rtp args' ret' a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (CurryAssignment args (RegEntry sym) (RegValue sym ret)
-> Assignment (RegEntry sym) args -> RegValue sym ret
forall k (ctx :: Ctx k) (f :: k -> Type) x.
CurryAssignmentClass ctx =>
CurryAssignment ctx f x -> Assignment f ctx -> x
forall (f :: CrucibleType -> Type) x.
CurryAssignment args f x -> Assignment f args -> x
Ctx.uncurryAssignment (RegValue sym ret -> RegEntry sym tp -> RegValue sym ret
forall a b. a -> b -> a
const (RegValue sym ret -> RegEntry sym tp -> RegValue sym ret)
-> (RegEntry sym ret -> RegValue sym ret)
-> RegEntry sym ret
-> RegEntry sym tp
-> RegValue sym ret
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RegEntry sym ret -> RegValue sym ret
forall sym (tp :: CrucibleType). RegEntry sym tp -> RegValue sym tp
regValue) Assignment (RegEntry sym) args
args)

      CtxRepr args
_ -> String
-> Declare
-> CtxRepr args
-> TypeRepr ret
-> SomeLLVMOverride p sym
forall a b c. (Show a, Show b) => String -> Declare -> a -> b -> c
panic_ String
"constOverride" Declare
decl CtxRepr args
argTys TypeRepr ret
retTy

-- | Make an override that always returns the same value.
fixedOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch)
              => TypeRepr ty
              -> (GlobalVar Mem -> sym -> IO (RegValue sym ty))
              -> [String]
              -> (L.Symbol -> ABI.DecodedName -> Bool)
              -> SomeCPPOverride p sym arch
fixedOverride :: forall sym (wptr :: Natural) (arch :: LLVMArch)
       (ty :: CrucibleType) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
TypeRepr ty
-> (GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> sym -> IO (RegValue sym ty))
-> [String]
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
fixedOverride TypeRepr ty
ty GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
-> sym -> IO (RegValue sym ty)
regval [String]
substrings =
  [String]
-> (forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
forall sym (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth (ArchWidth arch)) =>
[String]
-> (forall (args :: Ctx CrucibleType) (ret :: CrucibleType).
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
mkOverride [String]
substrings ((forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
  Declare
  -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
 -> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch)
-> (forall {args :: Ctx CrucibleType} {ret :: CrucibleType}.
    Declare
    -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym))
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
forall a b. (a -> b) -> a -> b
$ \Declare
decl CtxRepr args
argTys TypeRepr ret
retTy -> SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym)
forall a. a -> Maybe a
Just (SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym))
-> SomeLLVMOverride p sym -> Maybe (SomeLLVMOverride p sym)
forall a b. (a -> b) -> a -> b
$
    case TypeRepr ret -> TypeRepr ty -> Maybe (ret :~: ty)
forall {k} (f :: k -> Type) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
forall (a :: CrucibleType) (b :: CrucibleType).
TypeRepr a -> TypeRepr b -> Maybe (a :~: b)
testEquality TypeRepr ret
retTy TypeRepr ty
ty of
      Just ret :~: ty
Refl ->
        LLVMOverride p sym args ret -> SomeLLVMOverride p sym
forall p sym (args :: Ctx CrucibleType) (ret :: CrucibleType).
LLVMOverride p sym args ret -> SomeLLVMOverride p sym
SomeLLVMOverride (LLVMOverride p sym args ret -> SomeLLVMOverride p sym)
-> LLVMOverride p sym args ret -> SomeLLVMOverride p sym
forall a b. (a -> b) -> a -> b
$ Declare
-> CtxRepr args
-> TypeRepr ret
-> (forall {bak}.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
forall p sym (args :: Ctx CrucibleType) (ret :: CrucibleType).
Declare
-> CtxRepr args
-> TypeRepr ret
-> (forall bak.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall rtp (args' :: Ctx CrucibleType) (ret' :: CrucibleType).
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
LLVMOverride Declare
decl CtxRepr args
argTys TypeRepr ret
retTy ((forall {bak}.
  IsSymBackend sym bak =>
  GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
  -> bak
  -> Assignment (RegEntry sym) args
  -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
     OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
 -> LLVMOverride p sym args ret)
-> (forall {bak}.
    IsSymBackend sym bak =>
    GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> bak
    -> Assignment (RegEntry sym) args
    -> forall {rtp} {args' :: Ctx CrucibleType} {ret' :: CrucibleType}.
       OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret))
-> LLVMOverride p sym args ret
forall a b. (a -> b) -> a -> b
$ \GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
mem bak
bak Assignment (RegEntry sym) args
_args ->
          IO (RegValue sym ty)
-> OverrideSim p sym LLVM rtp args' ret' (RegValue sym ty)
forall a. IO a -> OverrideSim p sym LLVM rtp args' ret' a
forall (m :: Type -> Type) a. MonadIO m => IO a -> m a
liftIO (GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
-> sym -> IO (RegValue sym ty)
regval GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
mem (bak -> sym
forall sym bak. HasSymInterface sym bak => bak -> sym
backendGetSym bak
bak))

      Maybe (ret :~: ty)
_ -> String
-> Declare
-> CtxRepr args
-> TypeRepr ret
-> SomeLLVMOverride p sym
forall a b c. (Show a, Show b) => String -> Declare -> a -> b -> c
panic_ String
"fixedOverride" Declare
decl CtxRepr args
argTys TypeRepr ret
retTy

-- | Return @true@.
trueOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch)
             => [String]
             -> (L.Symbol -> ABI.DecodedName -> Bool)
             -> SomeCPPOverride p sym arch
trueOverride :: forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
[String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
trueOverride =
  TypeRepr (LLVMPointerType 1)
-> (GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> sym -> IO (RegValue sym (LLVMPointerType 1)))
-> [String]
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
forall sym (wptr :: Natural) (arch :: LLVMArch)
       (ty :: CrucibleType) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
TypeRepr ty
-> (GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> sym -> IO (RegValue sym ty))
-> [String]
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
fixedOverride (NatRepr 1 -> TypeRepr (LLVMPointerType 1)
forall (ty :: CrucibleType) (w :: Natural).
(1 <= w, ty ~ LLVMPointerType w) =>
NatRepr w -> TypeRepr ty
LLVMPointerRepr NatRepr 1
forall (n :: Natural). KnownNat n => NatRepr n
knownNat) ((GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
  -> sym -> IO (RegValue sym (LLVMPointerType 1)))
 -> [String]
 -> (Symbol -> DecodedName -> Bool)
 -> SomeCPPOverride p sym arch)
-> (GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
    -> sym -> IO (RegValue sym (LLVMPointerType 1)))
-> [String]
-> (Symbol -> DecodedName -> Bool)
-> SomeCPPOverride p sym arch
forall a b. (a -> b) -> a -> b
$ \GlobalVar ('IntrinsicType "LLVM_memory" 'EmptyCtx)
_mem sym
sym ->
    SymNat sym -> SymBV sym 1 -> LLVMPointer sym 1
forall sym (w :: Natural).
SymNat sym -> SymBV sym w -> LLVMPointer sym w
LLVMPointer (SymNat sym -> SymBV sym 1 -> LLVMPointer sym 1)
-> IO (SymNat sym) -> IO (SymBV sym 1 -> LLVMPointer sym 1)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> sym -> Natural -> IO (SymNat sym)
forall sym. IsExprBuilder sym => sym -> Natural -> IO (SymNat sym)
natLit sym
sym Natural
0 IO (SymBV sym 1 -> LLVMPointer sym 1)
-> IO (SymBV sym 1) -> IO (LLVMPointer sym 1)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> sym -> NatRepr 1 -> BV 1 -> IO (SymBV sym 1)
forall (w :: Natural).
(1 <= w) =>
sym -> NatRepr w -> BV w -> IO (SymBV sym w)
forall sym (w :: Natural).
(IsExprBuilder sym, 1 <= w) =>
sym -> NatRepr w -> BV w -> IO (SymBV sym w)
bvLit sym
sym (forall (n :: Natural). KnownNat n => NatRepr n
knownNat @1) (NatRepr 1 -> BV 1
forall (w :: Natural). (1 <= w) => NatRepr w -> BV w
BV.one NatRepr 1
forall (n :: Natural). KnownNat n => NatRepr n
knownNat)

------------------------------------------------------------------------
-- ** Declarations

------------------------------------------------------------------------
-- *** iostream

------------------------------------------------------------------------
-- **** basic_ostream

-- | Override for the \"put to\" operator, @<<@
--
-- This is the override for the 12th function signature listed here:
-- https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt
putToOverride12 :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch)
                => SomeCPPOverride p sym arch
putToOverride12 :: forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
SomeCPPOverride p sym arch
putToOverride12 =
  [String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
[String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
constOverride [String
"St",String
"ls",String
"basic_ostream"] ((Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch)
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
forall a b. (a -> b) -> a -> b
$ \Symbol
_ DecodedName
decodedName ->
    case DecodedName
decodedName of
      ABI.Function
         (ABI.NestedName
          []
          [ ABI.SubstitutionPrefix Substitution
ABI.SubStdNamespace
          , Prefix
_
          , ABI.UnqualifiedPrefix (ABI.SourceName String
"basic_ostream")
          , ABI.TemplateArgsPrefix [TemplateArg]
_
          ]
          (ABI.OperatorName Operator
ABI.OpShl))
          [ABI.PointerToType (ABI.FunctionType [CXXType]
_)] -> Bool
True
      DecodedName
_ -> Bool
False

-- | Override for the \"put to\" operator, @<<@
--
-- This is the override for the 9th function signature listed here (I think):
-- https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt
putToOverride9 :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch)
               => SomeCPPOverride p sym arch
putToOverride9 :: forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
SomeCPPOverride p sym arch
putToOverride9 =
  [String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
[String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
constOverride [String
"NSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc"] ((Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch)
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
forall a b. (a -> b) -> a -> b
$ \(L.Symbol String
nm) DecodedName
_ ->
    String
nm String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"_ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc"

-- | TODO: When @itanium-abi@ get support for parsing templates, make this a
-- more structured match
endlOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch)
             => SomeCPPOverride p sym arch
endlOverride :: forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
SomeCPPOverride p sym arch
endlOverride =
  [String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
[String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
identityOverride [String
"endl",String
"char_traits",String
"basic_ostream"] ((Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch)
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
forall a b. (a -> b) -> a -> b
$ \(L.Symbol String
nm) DecodedName
_decodedName ->
    [Bool] -> Bool
forall (t :: Type -> Type). Foldable t => t Bool -> Bool
and [ String
"endl"          String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` String
nm
        , String
"char_traits"   String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` String
nm
        , String
"basic_ostream" String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` String
nm
        ]

sentryOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch)
               => SomeCPPOverride p sym arch
sentryOverride :: forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
SomeCPPOverride p sym arch
sentryOverride =
  [String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
[String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
voidOverride [String
"basic_ostream", String
"sentry"] ((Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch)
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
forall a b. (a -> b) -> a -> b
$ \Symbol
_nm DecodedName
decodedName ->
    case DecodedName
decodedName of
      ABI.Function
         (ABI.NestedName
          []
          [ ABI.SubstitutionPrefix Substitution
ABI.SubStdNamespace
          , Prefix
_
          , ABI.UnqualifiedPrefix (ABI.SourceName String
"basic_ostream")
          , Prefix
_
          , ABI.UnqualifiedPrefix (ABI.SourceName String
"sentry")
          ]
          UnqualifiedName
_)
         [CXXType]
_ -> Bool
True
      DecodedName
_ -> Bool
False

-- | An override of the @bool@ operator (cast) on the @sentry@ class,
--
-- @sentry::operator bool()@
sentryBoolOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch)
                   => SomeCPPOverride p sym arch
sentryBoolOverride :: forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
SomeCPPOverride p sym arch
sentryBoolOverride =
  [String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
forall sym (wptr :: Natural) (arch :: LLVMArch) p.
(IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) =>
[String]
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
trueOverride [String
"basic_ostream", String
"sentry"] ((Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch)
-> (Symbol -> DecodedName -> Bool) -> SomeCPPOverride p sym arch
forall a b. (a -> b) -> a -> b
$ \Symbol
_nm DecodedName
decodedName ->
    case DecodedName
decodedName of
      ABI.Function
         (ABI.NestedName
          [CVQualifier
ABI.Const]
          [ ABI.SubstitutionPrefix Substitution
ABI.SubStdNamespace
          , Prefix
_
          , ABI.UnqualifiedPrefix (ABI.SourceName String
"basic_ostream")
          , Prefix
_
          , ABI.UnqualifiedPrefix (ABI.SourceName String
"sentry")
          ]
          (ABI.OperatorName (ABI.OpCast CXXType
ABI.BoolType)))
          [CXXType
ABI.VoidType] -> Bool
True
      DecodedName
_ -> Bool
False