crucible-llvm 0.6 → 0.7
raw patch · 29 files changed
+6996/−3940 lines, 29 filesdep ~basedep ~crucibledep ~crucible-symionew-uploaderPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, crucible, crucible-symio, llvm-pretty
API changes (from Hackage documentation)
- Lang.Crucible.LLVM.Globals: registerFunPtr :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> MemImpl sym -> String -> Symbol -> [Symbol] -> IO (LLVMPtr sym wptr, MemImpl sym)
- Lang.Crucible.LLVM.Intrinsics: bind_llvm_func :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMContext arch -> Symbol -> Assignment TypeRepr args -> TypeRepr ret -> FnState p sym LLVM args ret -> OverrideSim p sym LLVM rtp l a ()
- Lang.Crucible.LLVM.Intrinsics: bind_llvm_handle :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMContext arch -> Symbol -> FnHandle args ret -> FnState p sym LLVM args ret -> OverrideSim p sym LLVM rtp l a ()
- Lang.Crucible.LLVM.Intrinsics: type RegOverrideM p sym arch rtp l a = ReaderT (Declare, Maybe DecodedName, LLVMContext arch) (MaybeT (OverrideSim p sym LLVM rtp l a))
- Lang.Crucible.LLVM.MemModel: bindLLVMFunPtr :: (IsSymBackend sym bak, HasPtrWidth wptr) => bak -> Symbol -> FnHandle args ret -> MemImpl sym -> IO (MemImpl sym)
- Lang.Crucible.LLVM.MemModel: doMallocHandle :: (Typeable a, IsSymInterface sym, HasPtrWidth wptr) => sym -> AllocType -> String -> MemImpl sym -> a -> IO (LLVMPtr sym wptr, MemImpl sym)
+ Lang.Crucible.LLVM.Functions: allocFunPtr :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> MemImpl sym -> String -> IO (LLVMPtr sym wptr, MemImpl sym)
+ Lang.Crucible.LLVM.Functions: allocLLVMFunPtr :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> LLVMContext arch -> MemImpl sym -> Either Declare Define -> IO (LLVMPtr sym wptr, MemImpl sym)
+ Lang.Crucible.LLVM.Functions: allocLLVMFunPtrs :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> LLVMContext arch -> MemImpl sym -> Module -> IO (MemImpl sym)
+ Lang.Crucible.LLVM.Functions: bindLLVMCFG :: (IsSymInterface sym, HasPtrWidth wptr) => GlobalVar Mem -> Symbol -> CFG LLVM blocks init ret -> OverrideSim p sym LLVM rtp l a ()
+ Lang.Crucible.LLVM.Functions: bindLLVMFunPtr :: (IsSymBackend sym bak, HasPtrWidth wptr) => bak -> Symbol -> FnHandle args ret -> MemImpl sym -> IO (MemImpl sym)
+ Lang.Crucible.LLVM.Functions: bindLLVMFunc :: (IsSymInterface sym, HasPtrWidth wptr) => GlobalVar Mem -> Symbol -> Assignment TypeRepr args -> TypeRepr ret -> FnState p sym ext args ret -> OverrideSim p sym ext rtp l a ()
+ Lang.Crucible.LLVM.Functions: bindLLVMHandle :: (IsSymInterface sym, HasPtrWidth wptr) => GlobalVar Mem -> Symbol -> FnHandle args ret -> FnState p sym ext args ret -> OverrideSim p sym ext rtp l a ()
+ Lang.Crucible.LLVM.Functions: registerFunPtr :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> MemImpl sym -> String -> Symbol -> [Symbol] -> IO (LLVMPtr sym wptr, MemImpl sym)
+ Lang.Crucible.LLVM.Intrinsics: DarwinAliasMatch :: String -> TemplateMatcher
+ Lang.Crucible.LLVM.Intrinsics: MakeOverride :: (Declare -> Maybe DecodedName -> LLVMContext arch -> Maybe (SomeLLVMOverride p sym ext)) -> MakeOverride p sym ext arch
+ Lang.Crucible.LLVM.Intrinsics: [runMakeOverride] :: MakeOverride p sym ext arch -> Declare -> Maybe DecodedName -> LLVMContext arch -> Maybe (SomeLLVMOverride p sym ext)
+ Lang.Crucible.LLVM.Intrinsics: matches :: String -> TemplateMatcher -> Bool
+ Lang.Crucible.LLVM.Intrinsics: newtype MakeOverride p sym ext arch
+ Lang.Crucible.LLVM.Intrinsics: polymorphic1_vec_llvm_override :: forall p sym ext arch wptr. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => String -> (forall vecSz intSz. 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> SomeLLVMOverride p sym ext) -> OverrideTemplate p sym ext arch
+ Lang.Crucible.LLVM.Intrinsics: register_1arg_vec_polymorphic_override :: forall p sym ext arch wptr. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => String -> (forall vecSz intSz. 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> SomeLLVMOverride p sym ext) -> MakeOverride p sym ext arch
+ Lang.Crucible.LLVM.Intrinsics: stripDarwinAliases :: String -> String
+ Lang.Crucible.LLVM.Intrinsics.Cast: castLLVMArgs :: forall p sym ext bak args args'. IsSymBackend sym bak => FunctionName -> bak -> CtxRepr args' -> CtxRepr args -> Either ValCastError (ArgCast p sym ext args args')
+ Lang.Crucible.LLVM.Intrinsics.Cast: castLLVMRet :: IsSymBackend sym bak => FunctionName -> bak -> TypeRepr ret -> TypeRepr ret' -> Either ValCastError (ValCast p sym ext ret ret')
+ Lang.Crucible.LLVM.Intrinsics.Cast: data ArgCast p sym ext args args'
+ Lang.Crucible.LLVM.Intrinsics.Cast: data ValCast p sym ext tp tp'
+ Lang.Crucible.LLVM.Intrinsics.Cast: data ValCastError
+ Lang.Crucible.LLVM.Intrinsics.Cast: printValCastError :: ValCastError -> [String]
+ Lang.Crucible.LLVM.Intrinsics.LLVM: Poly1LLVMOverride :: (forall w. 1 <= w => NatRepr w -> SomeLLVMOverride p sym ext) -> Poly1LLVMOverride p sym ext
+ Lang.Crucible.LLVM.Intrinsics.LLVM: Poly1VecLLVMOverride :: (forall vecSz intSz. 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> SomeLLVMOverride p sym ext) -> Poly1VecLLVMOverride p sym ext
+ Lang.Crucible.LLVM.Intrinsics.LLVM: basic_llvm_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => [SomeLLVMOverride p sym ext]
+ Lang.Crucible.LLVM.Intrinsics.LLVM: bvSmax :: (IsExprBuilder sym, 1 <= w) => sym -> SymBV sym w -> SymBV sym w -> IO (SymBV sym w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: bvSmin :: (IsExprBuilder sym, 1 <= w) => sym -> SymBV sym w -> SymBV sym w -> IO (SymBV sym w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: bvUmax :: (IsExprBuilder sym, 1 <= w) => sym -> SymBV sym w -> SymBV sym w -> IO (SymBV sym w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: bvUmin :: (IsExprBuilder sym, 1 <= w) => sym -> SymBV sym w -> SymBV sym w -> IO (SymBV sym w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callLoadRelative :: (1 <= w, IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => GlobalVar Mem -> NatRepr w -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (LLVMPtr sym wptr)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callVectorReduce :: (RegValue sym tp -> RegValue sym tp -> IO (RegValue sym tp)) -> RegValue sym tp -> RegEntry sym (VectorType tp) -> OverrideSim p sym ext r args ret (RegValue sym tp)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callVectorReduceAdd :: (IsSymInterface sym, 1 <= intSz) => NatRepr intSz -> RegEntry sym (VectorType (BVType intSz)) -> OverrideSim p sym ext r args ret (SymBV sym intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callVectorReduceAnd :: (IsSymInterface sym, 1 <= intSz) => NatRepr intSz -> RegEntry sym (VectorType (BVType intSz)) -> OverrideSim p sym ext r args ret (SymBV sym intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callVectorReduceMul :: (IsSymInterface sym, 1 <= intSz) => NatRepr intSz -> RegEntry sym (VectorType (BVType intSz)) -> OverrideSim p sym ext r args ret (SymBV sym intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callVectorReduceOr :: (IsSymInterface sym, 1 <= intSz) => NatRepr intSz -> RegEntry sym (VectorType (BVType intSz)) -> OverrideSim p sym ext r args ret (SymBV sym intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callVectorReduceSmax :: (IsSymInterface sym, 1 <= intSz) => NatRepr intSz -> RegEntry sym (VectorType (BVType intSz)) -> OverrideSim p sym ext r args ret (SymBV sym intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callVectorReduceSmin :: (IsSymInterface sym, 1 <= intSz) => NatRepr intSz -> RegEntry sym (VectorType (BVType intSz)) -> OverrideSim p sym ext r args ret (SymBV sym intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callVectorReduceUmax :: (IsSymInterface sym, 1 <= intSz) => NatRepr intSz -> RegEntry sym (VectorType (BVType intSz)) -> OverrideSim p sym ext r args ret (SymBV sym intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callVectorReduceUmin :: (IsSymInterface sym, 1 <= intSz) => NatRepr intSz -> RegEntry sym (VectorType (BVType intSz)) -> OverrideSim p sym ext r args ret (SymBV sym intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callVectorReduceXor :: (IsSymInterface sym, 1 <= intSz) => NatRepr intSz -> RegEntry sym (VectorType (BVType intSz)) -> OverrideSim p sym ext r args ret (SymBV sym intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLoadRelative :: (1 <= w, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> LLVMPointerType wptr) ::> BVType w) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmVectorReduce :: 1 <= intSz => String -> (forall r args ret. IsSymInterface sym => NatRepr intSz -> RegEntry sym (VectorType (BVType intSz)) -> OverrideSim p sym ext r args ret (SymBV sym intSz)) -> NatRepr vecSz -> NatRepr intSz -> LLVMOverride p sym ext (EmptyCtx ::> VectorType (BVType intSz)) (BVType intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmVectorReduceAdd :: 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> LLVMOverride p sym ext (EmptyCtx ::> VectorType (BVType intSz)) (BVType intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmVectorReduceAnd :: 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> LLVMOverride p sym ext (EmptyCtx ::> VectorType (BVType intSz)) (BVType intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmVectorReduceMul :: 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> LLVMOverride p sym ext (EmptyCtx ::> VectorType (BVType intSz)) (BVType intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmVectorReduceOr :: 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> LLVMOverride p sym ext (EmptyCtx ::> VectorType (BVType intSz)) (BVType intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmVectorReduceSmax :: 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> LLVMOverride p sym ext (EmptyCtx ::> VectorType (BVType intSz)) (BVType intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmVectorReduceSmin :: 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> LLVMOverride p sym ext (EmptyCtx ::> VectorType (BVType intSz)) (BVType intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmVectorReduceUmax :: 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> LLVMOverride p sym ext (EmptyCtx ::> VectorType (BVType intSz)) (BVType intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmVectorReduceUmin :: 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> LLVMOverride p sym ext (EmptyCtx ::> VectorType (BVType intSz)) (BVType intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmVectorReduceXor :: 1 <= intSz => NatRepr vecSz -> NatRepr intSz -> LLVMOverride p sym ext (EmptyCtx ::> VectorType (BVType intSz)) (BVType intSz)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: mkNull :: (IsSymInterface sym, HasPtrWidth wptr) => OverrideSim p sym ext rtp args ret (LLVMPtr sym wptr)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: newtype Poly1LLVMOverride p sym ext
+ Lang.Crucible.LLVM.Intrinsics.LLVM: newtype Poly1VecLLVMOverride p sym ext
+ Lang.Crucible.LLVM.Intrinsics.LLVM: poly1_llvm_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => [(String, Poly1LLVMOverride p sym ext)]
+ Lang.Crucible.LLVM.Intrinsics.LLVM: poly1_vec_llvm_overrides :: IsSymInterface sym => [(String, Poly1VecLLVMOverride p sym ext)]
+ Lang.Crucible.LLVM.Intrinsics.Libc: libc_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions) => [SomeLLVMOverride p sym ext]
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvm__exp10Override :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvm__exp10fOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvm__isnandOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (BVType 32)
+ Lang.Crucible.LLVM.MemModel: [noSatisfyingWriteFreshConstant] :: MemOptions -> !Bool
+ Lang.Crucible.LLVM.MemModel: asMemMatchingArrayStore :: (IsSymInterface sym, 1 <= w) => sym -> NatRepr w -> LLVMPtr sym w -> SymBV sym w -> Mem sym -> IO (Maybe (Pred sym, SymArray sym (SingleCtx (BaseBVType w)) (BaseBVType 8)))
+ Lang.Crucible.LLVM.MemModel: loadArrayConcreteSizeRaw :: forall sym wptr. (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => sym -> MemImpl sym -> LLVMPtr sym wptr -> Natural -> Alignment -> IO (Either (Pred sym) (Pred sym, SymArray sym (SingleCtx (BaseBVType wptr)) (BaseBVType 8)))
+ Lang.Crucible.LLVM.MemModel: ptrToBv :: IsSymBackend sym bak => bak -> SimErrorReason -> LLVMPtr sym w -> IO (SymBV sym w)
+ Lang.Crucible.LLVM.MemModel.Generic: asMemMatchingArrayStore :: (IsSymInterface sym, 1 <= w) => sym -> NatRepr w -> LLVMPtr sym w -> SymBV sym w -> Mem sym -> IO (Maybe (Pred sym, SymArray sym (SingleCtx (BaseBVType w)) (BaseBVType 8)))
+ Lang.Crucible.LLVM.MemModel.MemLog: [memArrayBlocks] :: Mem sym -> Set Natural
+ Lang.Crucible.LLVM.MemModel.MemLog: memInsertArrayBlock :: IsExprBuilder sym => SymNat sym -> Mem sym -> Mem sym
+ Lang.Crucible.LLVM.MemModel.MemLog: memMemberArrayBlock :: IsExprBuilder sym => SymNat sym -> Mem sym -> Bool
+ Lang.Crucible.LLVM.MemModel.MemLog: writeSourceSize :: (IsExprBuilder sym, 1 <= w) => sym -> NatRepr w -> WriteSource sym w -> MaybeT IO (SymBV sym w)
+ Lang.Crucible.LLVM.MemModel.Partial: ptrToBv :: IsSymBackend sym bak => bak -> SimErrorReason -> LLVMPtr sym w -> IO (SymBV sym w)
+ Lang.Crucible.LLVM.MemModel.Pointer: ConcLLVMPtr :: Integer -> BV w -> NatRepr w -> ConcLLVMPtr w
+ Lang.Crucible.LLVM.MemModel.Pointer: [concBlock] :: ConcLLVMPtr w -> Integer
+ Lang.Crucible.LLVM.MemModel.Pointer: [concOffset] :: ConcLLVMPtr w -> BV w
+ Lang.Crucible.LLVM.MemModel.Pointer: [concWidth] :: ConcLLVMPtr w -> NatRepr w
+ Lang.Crucible.LLVM.MemModel.Pointer: concLLVMPtr :: IsExprBuilder sym => (forall tp. SymExpr sym tp -> IO (GroundValue tp)) -> RegValue sym (LLVMPointerType w) -> IO (ConcLLVMPtr w)
+ Lang.Crucible.LLVM.MemModel.Pointer: concLLVMPtrToSymbolic :: (IsExprBuilder sym, 1 <= w) => sym -> ConcLLVMPtr w -> IO (RegValue sym (LLVMPointerType w))
+ Lang.Crucible.LLVM.MemModel.Pointer: concPtrFn :: IntrinsicConcFn t "LLVM_pointer"
+ Lang.Crucible.LLVM.MemModel.Pointer: concPtrFnMap :: MapF SymbolRepr (IntrinsicConcFn t)
+ Lang.Crucible.LLVM.MemModel.Pointer: concToSymPtrFn :: IntrinsicConcToSymFn "LLVM_pointer"
+ Lang.Crucible.LLVM.MemModel.Pointer: concToSymPtrFnMap :: MapF SymbolRepr IntrinsicConcToSymFn
+ Lang.Crucible.LLVM.MemModel.Pointer: data ConcLLVMPtr w
+ Lang.Crucible.LLVM.MemModel.Pointer: ptrIsBv :: IsSymInterface sym => sym -> LLVMPtr sym w -> IO (Pred sym)
+ Lang.Crucible.LLVM.MemModel.Pointer: ptrSameAlloc :: (1 <= w, IsSymInterface sym) => sym -> LLVMPtr sym w -> LLVMPtr sym w -> IO (Pred sym)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: AfterFixpoint :: FixpointRecord sym wptr blocks args -> FixpointState sym wptr blocks args
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: BeforeFixpoint :: FixpointState sym wptr blocks args
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: CallFrameContext :: MapF (BlockID blocks) (FixpointState sym wptr blocks) -> [Some (BlockID blocks)] -> CFG ext blocks init ret -> Map (Some (BlockID blocks)) (Some (BlockID blocks)) -> Set (Some (BlockID blocks)) -> CallFrameContext sym wptr ext init ret blocks
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: CheckFixpoint :: FixpointRecord sym wptr blocks args -> SomeSymFn sym -> Some (Assignment (SymExpr sym)) -> Pred sym -> FixpointState sym wptr blocks args
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: ComputeFixpoint :: FixpointRecord sym wptr blocks args -> FixpointState sym wptr blocks args
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: ExecutionFeatureContext :: FnHandleMap (SomeCallFrameContext sym wptr ext) -> [SomeSymFn sym] -> [Pred sym] -> ExecutionFeatureContext sym wptr ext
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: FixpointEntry :: SymExpr sym tp -> SymExpr sym tp -> FixpointEntry sym tp
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: SomeCallFrameContext :: CallFrameContext sym wptr ext init ret blocks -> SomeCallFrameContext sym wptr ext init ret
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: [bodyValue] :: FixpointEntry sym tp -> SymExpr sym tp
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: [callFrameContextCFG] :: CallFrameContext sym wptr ext init ret blocks -> CFG ext blocks init ret
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: [callFrameContextFixpointStates] :: CallFrameContext sym wptr ext init ret blocks -> MapF (BlockID blocks) (FixpointState sym wptr blocks)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: [callFrameContextLoopHeaderBlockIds] :: CallFrameContext sym wptr ext init ret blocks -> Set (Some (BlockID blocks))
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: [callFrameContextLoopHeaders] :: CallFrameContext sym wptr ext init ret blocks -> [Some (BlockID blocks)]
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: [callFrameContextParentLoop] :: CallFrameContext sym wptr ext init ret blocks -> Map (Some (BlockID blocks)) (Some (BlockID blocks))
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: [executionFeatureContextFixpointStates] :: ExecutionFeatureContext sym wptr ext -> FnHandleMap (SomeCallFrameContext sym wptr ext)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: [executionFeatureContextInvPreds] :: ExecutionFeatureContext sym wptr ext -> [SomeSymFn sym]
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: [executionFeatureContextLoopFunEquivConds] :: ExecutionFeatureContext sym wptr ext -> [Pred sym]
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: [headerValue] :: FixpointEntry sym tp -> SymExpr sym tp
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: data CallFrameContext sym wptr ext init ret blocks
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: data ExecutionFeatureContext sym wptr ext
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: data FixpointEntry sym tp
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: data FixpointState sym wptr blocks args
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: data SomeCallFrameContext sym wptr ext init ret
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance (s GHC.Types.~ Data.Parameterized.Map.MapF (What4.Interface.SymExpr sym) (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.FixpointEntry sym)) => Control.Monad.State.Class.MonadState s (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.FixpointMonad sym)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance Control.Monad.Fail.MonadFail (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.FixpointMonad sym)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance Control.Monad.IO.Class.MonadIO (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.FixpointMonad sym)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance Data.Parameterized.Classes.OrdF (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.FixpointEntry sym) => Data.Type.Equality.TestEquality (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.FixpointEntry sym)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance Data.Parameterized.Classes.OrdF (What4.Interface.SymExpr sym) => Data.Parameterized.Classes.OrdF (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.FixpointEntry sym)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance Data.Parameterized.Classes.OrdF (What4.Interface.SymExpr sym) => GHC.Classes.Eq (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.MemLocation sym w)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance Data.Parameterized.Classes.OrdF (What4.Interface.SymExpr sym) => GHC.Classes.Ord (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.MemLocation sym w)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance GHC.Base.Applicative (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.FixpointMonad sym)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance GHC.Base.Functor (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.FixpointMonad sym)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance GHC.Base.Monad (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.FixpointMonad sym)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance GHC.Classes.Eq (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.CallFrameHandle init ret blocks)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance GHC.Classes.Ord (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.CallFrameHandle init ret blocks)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: instance GHC.Show.Show (Lang.Crucible.LLVM.SimpleLoopFixpointCHC.CallFrameHandle init ret blocks)
+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC: simpleLoopFixpoint :: (IsSymInterface sym, sym ~ ExprBuilder t st fs, HasPtrWidth wptr, KnownNat wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => sym -> CFG ext blocks init ret -> GlobalVar Mem -> Maybe (MapF (SymExpr sym) (FixpointEntry sym) -> Pred sym -> IO (MapF (SymExpr sym) (SymExpr sym), Maybe (Pred sym))) -> IO (ExecutionFeature p sym ext rtp, IORef (ExecutionFeatureContext sym wptr ext))
- Lang.Crucible.LLVM: register_llvm_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions) => Module -> [OverrideTemplate p sym arch rtp l a] -> [OverrideTemplate p sym arch rtp l a] -> LLVMContext arch -> OverrideSim p sym LLVM rtp l a ()
+ Lang.Crucible.LLVM: register_llvm_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions) => Module -> [OverrideTemplate p sym LLVM arch] -> [OverrideTemplate p sym LLVM arch] -> LLVMContext arch -> OverrideSim p sym LLVM rtp l a ([SomeLLVMOverride p sym LLVM], [SomeLLVMOverride p sym LLVM])
- Lang.Crucible.LLVM.Intrinsics: LLVMOverride :: Declare -> CtxRepr args -> TypeRepr ret -> (forall bak. IsSymBackend sym bak => GlobalVar Mem -> bak -> Assignment (RegEntry sym) args -> forall rtp args' ret'. OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret)) -> LLVMOverride p sym args ret
+ Lang.Crucible.LLVM.Intrinsics: LLVMOverride :: Declare -> CtxRepr args -> TypeRepr ret -> (IsSymInterface sym => GlobalVar Mem -> Assignment (RegEntry sym) args -> forall rtp args' ret'. OverrideSim p sym ext rtp args' ret' (RegValue sym ret)) -> LLVMOverride p sym ext args ret
- Lang.Crucible.LLVM.Intrinsics: OverrideTemplate :: TemplateMatcher -> RegOverrideM p sym arch rtp l a () -> OverrideTemplate p sym arch rtp l a
+ Lang.Crucible.LLVM.Intrinsics: OverrideTemplate :: TemplateMatcher -> MakeOverride p sym ext arch -> OverrideTemplate p sym ext arch
- Lang.Crucible.LLVM.Intrinsics: SomeLLVMOverride :: LLVMOverride p sym args ret -> SomeLLVMOverride p sym
+ Lang.Crucible.LLVM.Intrinsics: SomeLLVMOverride :: LLVMOverride p sym ext args ret -> SomeLLVMOverride p sym ext
- Lang.Crucible.LLVM.Intrinsics: [llvmOverride_args] :: LLVMOverride p sym args ret -> CtxRepr args
+ Lang.Crucible.LLVM.Intrinsics: [llvmOverride_args] :: LLVMOverride p sym ext args ret -> CtxRepr args
- Lang.Crucible.LLVM.Intrinsics: [llvmOverride_declare] :: LLVMOverride p sym args ret -> Declare
+ Lang.Crucible.LLVM.Intrinsics: [llvmOverride_declare] :: LLVMOverride p sym ext args ret -> Declare
- Lang.Crucible.LLVM.Intrinsics: [llvmOverride_def] :: LLVMOverride p sym args ret -> forall bak. IsSymBackend sym bak => GlobalVar Mem -> bak -> Assignment (RegEntry sym) args -> forall rtp args' ret'. OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret)
+ Lang.Crucible.LLVM.Intrinsics: [llvmOverride_def] :: LLVMOverride p sym ext args ret -> IsSymInterface sym => GlobalVar Mem -> Assignment (RegEntry sym) args -> forall rtp args' ret'. OverrideSim p sym ext rtp args' ret' (RegValue sym ret)
- Lang.Crucible.LLVM.Intrinsics: [llvmOverride_ret] :: LLVMOverride p sym args ret -> TypeRepr ret
+ Lang.Crucible.LLVM.Intrinsics: [llvmOverride_ret] :: LLVMOverride p sym ext args ret -> TypeRepr ret
- Lang.Crucible.LLVM.Intrinsics: [overrideTemplateAction] :: OverrideTemplate p sym arch rtp l a -> RegOverrideM p sym arch rtp l a ()
+ Lang.Crucible.LLVM.Intrinsics: [overrideTemplateAction] :: OverrideTemplate p sym ext arch -> MakeOverride p sym ext arch
- Lang.Crucible.LLVM.Intrinsics: [overrideTemplateMatcher] :: OverrideTemplate p sym arch rtp l a -> TemplateMatcher
+ Lang.Crucible.LLVM.Intrinsics: [overrideTemplateMatcher] :: OverrideTemplate p sym ext arch -> TemplateMatcher
- Lang.Crucible.LLVM.Intrinsics: alloc_and_register_override :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> LLVMContext arch -> LLVMOverride p sym args ret -> [Symbol] -> OverrideSim p sym LLVM rtp l a ()
+ Lang.Crucible.LLVM.Intrinsics: alloc_and_register_override :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> LLVMContext arch -> LLVMOverride p sym LLVM args ret -> [Symbol] -> OverrideSim p sym LLVM rtp l a ()
- Lang.Crucible.LLVM.Intrinsics: basic_llvm_override :: forall p args ret sym arch wptr l a rtp. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym args ret -> OverrideTemplate p sym arch rtp l a
+ Lang.Crucible.LLVM.Intrinsics: basic_llvm_override :: forall p args ret sym ext arch wptr. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ext args ret -> OverrideTemplate p sym ext arch
- Lang.Crucible.LLVM.Intrinsics: build_llvm_override :: HasLLVMAnn sym => FunctionName -> CtxRepr args -> TypeRepr ret -> CtxRepr args' -> TypeRepr ret' -> (forall bak rtp' l' a'. IsSymBackend sym bak => bak -> Assignment (RegEntry sym) args -> OverrideSim p sym LLVM rtp' l' a' (RegValue sym ret)) -> OverrideSim p sym LLVM rtp l a (Override p sym LLVM args' ret')
+ Lang.Crucible.LLVM.Intrinsics: build_llvm_override :: HasLLVMAnn sym => FunctionName -> CtxRepr args -> TypeRepr ret -> CtxRepr args' -> TypeRepr ret' -> (forall rtp' l' a'. IsSymInterface sym => Assignment (RegEntry sym) args -> OverrideSim p sym ext rtp' l' a' (RegValue sym ret)) -> OverrideSim p sym ext rtp l a (Override p sym ext args' ret')
- Lang.Crucible.LLVM.Intrinsics: data LLVMOverride p sym args ret
+ Lang.Crucible.LLVM.Intrinsics: data LLVMOverride p sym ext args ret
- Lang.Crucible.LLVM.Intrinsics: data OverrideTemplate p sym arch rtp l a
+ Lang.Crucible.LLVM.Intrinsics: data OverrideTemplate p sym ext arch
- Lang.Crucible.LLVM.Intrinsics: data SomeLLVMOverride p sym
+ Lang.Crucible.LLVM.Intrinsics: data SomeLLVMOverride p sym ext
- Lang.Crucible.LLVM.Intrinsics: do_register_llvm_override :: forall p args ret sym arch wptr l a rtp. (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym) => LLVMContext arch -> LLVMOverride p sym args ret -> OverrideSim p sym LLVM rtp l a ()
+ Lang.Crucible.LLVM.Intrinsics: do_register_llvm_override :: forall p args ret sym ext arch wptr l a rtp. (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym) => LLVMContext arch -> LLVMOverride p sym ext args ret -> OverrideSim p sym ext rtp l a ()
- Lang.Crucible.LLVM.Intrinsics: polymorphic1_llvm_override :: forall p sym arch wptr l a rtp. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => String -> (forall w. 1 <= w => NatRepr w -> SomeLLVMOverride p sym) -> OverrideTemplate p sym arch rtp l a
+ Lang.Crucible.LLVM.Intrinsics: polymorphic1_llvm_override :: forall p sym ext arch wptr. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => String -> (forall w. 1 <= w => NatRepr w -> SomeLLVMOverride p sym ext) -> OverrideTemplate p sym ext arch
- Lang.Crucible.LLVM.Intrinsics: register_1arg_polymorphic_override :: forall p sym arch wptr l a rtp. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => String -> (forall w. 1 <= w => NatRepr w -> SomeLLVMOverride p sym) -> RegOverrideM p sym arch rtp l a ()
+ Lang.Crucible.LLVM.Intrinsics: register_1arg_polymorphic_override :: forall p sym ext arch wptr. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => String -> (forall w. 1 <= w => NatRepr w -> SomeLLVMOverride p sym ext) -> MakeOverride p sym ext arch
- Lang.Crucible.LLVM.Intrinsics: register_llvm_override :: forall p args ret sym arch wptr l a rtp. (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym) => LLVMOverride p sym args ret -> RegOverrideM p sym arch rtp l a ()
+ Lang.Crucible.LLVM.Intrinsics: register_llvm_override :: forall p args ret sym ext arch wptr rtp l a. (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym) => LLVMOverride p sym ext args ret -> Declare -> LLVMContext arch -> OverrideSim p sym ext rtp l a ()
- Lang.Crucible.LLVM.Intrinsics: register_llvm_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions) => Module -> [OverrideTemplate p sym arch rtp l a] -> [OverrideTemplate p sym arch rtp l a] -> LLVMContext arch -> OverrideSim p sym LLVM rtp l a ()
+ Lang.Crucible.LLVM.Intrinsics: register_llvm_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions) => Module -> [OverrideTemplate p sym LLVM arch] -> [OverrideTemplate p sym LLVM arch] -> LLVMContext arch -> OverrideSim p sym LLVM rtp l a ([SomeLLVMOverride p sym LLVM], [SomeLLVMOverride p sym LLVM])
- Lang.Crucible.LLVM.Intrinsics: register_llvm_overrides_ :: LLVMContext arch -> [OverrideTemplate p sym arch rtp l a] -> [Declare] -> OverrideSim p sym LLVM rtp l a ()
+ Lang.Crucible.LLVM.Intrinsics: register_llvm_overrides_ :: (IsSymInterface sym, HasLLVMAnn sym) => LLVMContext arch -> [OverrideTemplate p sym ext arch] -> [Declare] -> OverrideSim p sym ext rtp l a [SomeLLVMOverride p sym ext]
- Lang.Crucible.LLVM.Intrinsics.LLVM: callBitreverse :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callBitreverse :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callCopysign :: forall fi p sym bak ext r args ret. IsSymBackend sym bak => bak -> RegEntry sym (FloatType fi) -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callCopysign :: forall fi p sym ext r args ret. IsSymInterface sym => RegEntry sym (FloatType fi) -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callCtlz :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callCtlz :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callCtpop :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callCtpop :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callCttz :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callCttz :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callFshl :: (1 <= w, IsSymBackend sym bak) => bak -> NatRepr w -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callFshl :: (1 <= w, IsSymInterface sym) => NatRepr w -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callFshr :: (1 <= w, IsSymBackend sym bak) => bak -> NatRepr w -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callFshr :: (1 <= w, IsSymInterface sym) => NatRepr w -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callIsFpclass :: forall fi p sym bak ext r args ret. IsSymBackend sym bak => bak -> RegEntry sym (FloatType fi) -> RegEntry sym (BVType 32) -> OverrideSim p sym ext r args ret (RegValue sym (BVType 1))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callIsFpclass :: forall fi p sym ext r args ret. IsSymInterface sym => RegEntry sym (FloatType fi) -> RegEntry sym (BVType 32) -> OverrideSim p sym ext r args ret (RegValue sym (BVType 1))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callObjectsize :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> NatRepr w -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callObjectsize :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> NatRepr w -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callObjectsize_null :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> NatRepr w -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType 1) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callObjectsize_null :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> NatRepr w -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType 1) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callObjectsize_null_dynamic :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> NatRepr w -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType 1) -> RegEntry sym (BVType 1) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callObjectsize_null_dynamic :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> NatRepr w -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType 1) -> RegEntry sym (BVType 1) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callSaddWithOverflow :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callSaddWithOverflow :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callSmax :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callSmax :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callSmin :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callSmin :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callSmulWithOverflow :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callSmulWithOverflow :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callSsubWithOverflow :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callSsubWithOverflow :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callStoreudq :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (VectorType (BVType 8)) -> OverrideSim p sym ext r args ret ()
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callStoreudq :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (VectorType (BVType 8)) -> OverrideSim p sym ext r args ret ()
- Lang.Crucible.LLVM.Intrinsics.LLVM: callUaddWithOverflow :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callUaddWithOverflow :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callUmax :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callUmax :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callUmin :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callUmin :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callUmulWithOverflow :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callUmulWithOverflow :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callUsubWithOverflow :: (1 <= w, IsSymBackend sym bak) => bak -> GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callUsubWithOverflow :: (1 <= w, IsSymInterface sym) => GlobalVar Mem -> RegEntry sym (BVType w) -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (StructType ((EmptyCtx ::> BVType w) ::> BVType 1)))
- Lang.Crucible.LLVM.Intrinsics.LLVM: callX86_pclmulqdq :: forall p sym bak ext wptr r args ret. (IsSymBackend sym bak, HasPtrWidth wptr) => bak -> GlobalVar Mem -> RegEntry sym (VectorType (BVType 64)) -> RegEntry sym (VectorType (BVType 64)) -> RegEntry sym (BVType 8) -> OverrideSim p sym ext r args ret (RegValue sym (VectorType (BVType 64)))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: callX86_pclmulqdq :: forall p sym ext wptr r args ret. (IsSymInterface sym, HasPtrWidth wptr) => GlobalVar Mem -> RegEntry sym (VectorType (BVType 64)) -> RegEntry sym (VectorType (BVType 64)) -> RegEntry sym (BVType 8) -> OverrideSim p sym ext r args ret (RegValue sym (VectorType (BVType 64)))
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmAbsOverride :: (1 <= w, IsSymInterface sym, HasLLVMAnn sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType 1) (BVType w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmAbsOverride :: (1 <= w, IsSymInterface sym, HasLLVMAnn sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType 1) (BVType w)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmAssumeOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmAssumeOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmBSwapOverride :: forall width sym p. (1 <= width, IsSymInterface sym) => NatRepr width -> LLVMOverride p sym (EmptyCtx ::> BVType (width * 8)) (BVType (width * 8))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmBSwapOverride :: forall width sym p ext. (1 <= width, IsSymInterface sym) => NatRepr width -> LLVMOverride p sym ext (EmptyCtx ::> BVType (width * 8)) (BVType (width * 8))
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmBitreverse :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym (EmptyCtx ::> BVType w) (BVType w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmBitreverse :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext (EmptyCtx ::> BVType w) (BVType w)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCeilOverride_F32 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCeilOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCeilOverride_F64 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCeilOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCopysignOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCopysignOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCopysignOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCopysignOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCosOverride_F32 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCosOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCosOverride_F64 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCosOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCtlz :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType 1) (BVType w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCtlz :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType 1) (BVType w)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCtpop :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym (EmptyCtx ::> BVType w) (BVType w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCtpop :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext (EmptyCtx ::> BVType w) (BVType w)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCttz :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType 1) (BVType w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmCttz :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType 1) (BVType w)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmExp2Override_F32 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmExp2Override_F32 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmExp2Override_F64 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmExp2Override_F64 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmExpOverride_F32 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmExpOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmExpOverride_F64 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmExpOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmExpectOverride :: (IsSymInterface sym, 1 <= width) => NatRepr width -> LLVMOverride p sym ((EmptyCtx ::> BVType width) ::> BVType width) (BVType width)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmExpectOverride :: (IsSymInterface sym, 1 <= width) => NatRepr width -> LLVMOverride p sym ext ((EmptyCtx ::> BVType width) ::> BVType width) (BVType width)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFabsF32 :: forall sym p. IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFabsF32 :: forall sym p ext. IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFabsF64 :: forall sym p. IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFabsF64 :: forall sym p ext. IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFloorOverride_F32 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFloorOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFloorOverride_F64 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFloorOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFmaOverride_F32 :: forall sym p. IsSymInterface sym => LLVMOverride p sym (((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFmaOverride_F32 :: forall sym p ext. IsSymInterface sym => LLVMOverride p sym ext (((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFmaOverride_F64 :: forall sym p. IsSymInterface sym => LLVMOverride p sym (((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFmaOverride_F64 :: forall sym p ext. IsSymInterface sym => LLVMOverride p sym ext (((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFmuladdOverride_F32 :: forall sym p. IsSymInterface sym => LLVMOverride p sym (((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFmuladdOverride_F32 :: forall sym p ext. IsSymInterface sym => LLVMOverride p sym ext (((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFmuladdOverride_F64 :: forall sym p. IsSymInterface sym => LLVMOverride p sym (((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFmuladdOverride_F64 :: forall sym p ext. IsSymInterface sym => LLVMOverride p sym ext (((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFshl :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym (((EmptyCtx ::> BVType w) ::> BVType w) ::> BVType w) (BVType w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFshl :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext (((EmptyCtx ::> BVType w) ::> BVType w) ::> BVType w) (BVType w)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFshr :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym (((EmptyCtx ::> BVType w) ::> BVType w) ::> BVType w) (BVType w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmFshr :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext (((EmptyCtx ::> BVType w) ::> BVType w) ::> BVType w) (BVType w)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmInvariantEndOverride :: (IsSymInterface sym, HasPtrWidth wptr) => NatRepr width -> LLVMOverride p sym (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 64) ::> LLVMPointerType wptr) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmInvariantEndOverride :: (IsSymInterface sym, HasPtrWidth wptr) => NatRepr width -> LLVMOverride p sym ext (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 64) ::> LLVMPointerType wptr) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmInvariantEndOverride_opaque :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 64) ::> LLVMPointerType wptr) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmInvariantEndOverride_opaque :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 64) ::> LLVMPointerType wptr) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmInvariantStartOverride :: (IsSymInterface sym, HasPtrWidth wptr) => NatRepr width -> LLVMOverride p sym ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmInvariantStartOverride :: (IsSymInterface sym, HasPtrWidth wptr) => NatRepr width -> LLVMOverride p sym ext ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmInvariantStartOverride_opaque :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmInvariantStartOverride_opaque :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmIsFpclassOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType SingleFloat) ::> BVType 32) (BVType 1)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmIsFpclassOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType SingleFloat) ::> BVType 32) (BVType 1)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmIsFpclassOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType DoubleFloat) ::> BVType 32) (BVType 1)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmIsFpclassOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType DoubleFloat) ::> BVType 32) (BVType 1)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLifetimeEndOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLifetimeEndOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLifetimeOverrideOverload :: forall width sym wptr p. (1 <= width, KnownNat width, IsSymInterface sym, HasPtrWidth wptr) => String -> NatRepr width -> LLVMOverride p sym ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLifetimeOverrideOverload :: forall width sym wptr p ext. (1 <= width, KnownNat width, IsSymInterface sym, HasPtrWidth wptr) => String -> NatRepr width -> LLVMOverride p sym ext ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLifetimeOverrideOverload_opaque :: forall sym wptr p. (IsSymInterface sym, HasPtrWidth wptr) => String -> LLVMOverride p sym ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLifetimeOverrideOverload_opaque :: forall sym wptr p ext. (IsSymInterface sym, HasPtrWidth wptr) => String -> LLVMOverride p sym ext ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLifetimeStartOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLifetimeStartOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((EmptyCtx ::> BVType 64) ::> LLVMPointerType wptr) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLog10Override_F32 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLog10Override_F32 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLog10Override_F64 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLog10Override_F64 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLog2Override_F32 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLog2Override_F32 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLog2Override_F64 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLog2Override_F64 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLogOverride_F32 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLogOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLogOverride_F64 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmLogOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_32 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym (((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_32 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext (((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_32_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_32_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_32_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_32_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_64 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym (((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_64 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext (((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_64_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_64_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_64_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemcpyOverride_8_8_64_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_32 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym (((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_32 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext (((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_32_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_32_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_32_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_32_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_64 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym (((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_64 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext (((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_64_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_64_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_64_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemmoveOverride_8_8_64_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 64) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_32 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym (((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 32) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_32 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ext (((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 32) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_32_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_32_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_32_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_32_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_64 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym (((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 64) ::> BVType 32) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_64 :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ext (((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 64) ::> BVType 32) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_64_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 64) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_64_noalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 64) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_64_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 64) ::> BVType 1) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmMemsetOverride_8_64_noalign_opaque :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 8) ::> BVType 64) ::> BVType 1) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_32 :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_32 :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_32_null :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_32_null :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_32_null_dynamic :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) ::> BVType 1) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_32_null_dynamic :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) ::> BVType 1) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_32_null_dynamic_opaque :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) ::> BVType 1) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_32_null_dynamic_opaque :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) ::> BVType 1) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_64 :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) (BVType 64)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_64 :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) (BVType 64)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_64_null :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) (BVType 64)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_64_null :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) (BVType 64)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_64_null_dynamic :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) ::> BVType 1) (BVType 64)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_64_null_dynamic :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) ::> BVType 1) (BVType 64)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_64_null_dynamic_opaque :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) ::> BVType 1) (BVType 64)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmObjectsizeOverride_64_null_dynamic_opaque :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 1) ::> BVType 1) ::> BVType 1) (BVType 64)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmPowOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmPowOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmPowOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmPowOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmPrefetchOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 32) ::> BVType 32) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmPrefetchOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 32) ::> BVType 32) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmPrefetchOverride_opaque :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 32) ::> BVType 32) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmPrefetchOverride_opaque :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 32) ::> BVType 32) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmPrefetchOverride_preLLVM10 :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 32) ::> BVType 32) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmPrefetchOverride_preLLVM10 :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType 32) ::> BVType 32) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSaddWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSaddWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSinOverride_F32 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSinOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSinOverride_F64 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSinOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSmax :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType w) (BVType w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSmax :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType w) (BVType w)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSmin :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType w) (BVType w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSmin :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType w) (BVType w)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSmulWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSmulWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSqrtOverride_F32 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSqrtOverride_F32 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSqrtOverride_F64 :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSqrtOverride_F64 :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSsubWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmSsubWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmStackrestore :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmStackrestore :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmStacksave :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym EmptyCtx (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmStacksave :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext EmptyCtx (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmTrapOverride :: IsSymInterface sym => LLVMOverride p sym EmptyCtx UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmTrapOverride :: IsSymInterface sym => LLVMOverride p sym ext EmptyCtx UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUBSanTrapOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> BVType 8) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUBSanTrapOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> BVType 8) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUaddWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUaddWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUmax :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType w) (BVType w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUmax :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType w) (BVType w)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUmin :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType w) (BVType w)
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUmin :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType w) (BVType w)
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUmulWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUmulWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUsubWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmUsubWithOverflow :: (1 <= w, IsSymInterface sym) => NatRepr w -> LLVMOverride p sym ext ((EmptyCtx ::> BVType w) ::> BVType w) (StructType ((EmptyCtx ::> BVType w) ::> BVType 1))
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmX86_SSE2_storeu_dq :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ((EmptyCtx ::> LLVMPointerType wptr) ::> VectorType (BVType 8)) UnitType
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmX86_SSE2_storeu_dq :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((EmptyCtx ::> LLVMPointerType wptr) ::> VectorType (BVType 8)) UnitType
- Lang.Crucible.LLVM.Intrinsics.LLVM: llvmX86_pclmulqdq :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym (((EmptyCtx ::> VectorType (BVType 64)) ::> VectorType (BVType 64)) ::> BVType 8) (VectorType (BVType 64))
+ Lang.Crucible.LLVM.Intrinsics.LLVM: llvmX86_pclmulqdq :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext (((EmptyCtx ::> VectorType (BVType 64)) ::> VectorType (BVType 64)) ::> BVType 8) (VectorType (BVType 64))
- Lang.Crucible.LLVM.Intrinsics.Libc: callAbs :: forall w p sym bak ext r args ret. (1 <= w, IsSymBackend sym bak, HasLLVMAnn sym) => bak -> CallStack -> CheckAbsIntMin -> NatRepr w -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callAbs :: forall w p sym ext r args ret. (1 <= w, IsSymInterface sym, HasLLVMAnn sym) => CallStack -> CheckAbsIntMin -> NatRepr w -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.Libc: callAssert :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions) => Bool -> GlobalVar Mem -> bak -> Assignment (RegEntry sym) ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> LLVMPointerType wptr) -> forall r args reg. OverrideSim p sym ext r args reg (RegValue sym UnitType)
+ Lang.Crucible.LLVM.Intrinsics.Libc: callAssert :: (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions) => GlobalVar Mem -> Assignment (RegEntry sym) ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> LLVMPointerType wptr) -> forall r args reg. OverrideSim p sym ext r args reg (RegValue sym UnitType)
- Lang.Crucible.LLVM.Intrinsics.Libc: callBSwap :: (1 <= width, IsSymBackend sym bak) => bak -> NatRepr width -> RegEntry sym (BVType (width * 8)) -> OverrideSim p sym ext r args ret (RegValue sym (BVType (width * 8)))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callBSwap :: (1 <= width, IsSymInterface sym) => NatRepr width -> RegEntry sym (BVType (width * 8)) -> OverrideSim p sym ext r args ret (RegValue sym (BVType (width * 8)))
- Lang.Crucible.LLVM.Intrinsics.Libc: callBSwapIfLittleEndian :: (1 <= width, IsSymBackend sym bak, ?lc :: TypeContext) => bak -> NatRepr width -> RegEntry sym (BVType (width * 8)) -> OverrideSim p sym ext r args ret (RegValue sym (BVType (width * 8)))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callBSwapIfLittleEndian :: (1 <= width, IsSymInterface sym, ?lc :: TypeContext) => NatRepr width -> RegEntry sym (BVType (width * 8)) -> OverrideSim p sym ext r args ret (RegValue sym (BVType (width * 8)))
- Lang.Crucible.LLVM.Intrinsics.Libc: callCalloc :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> Alignment -> RegEntry sym (BVType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callCalloc :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => GlobalVar Mem -> Alignment -> RegEntry sym (BVType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))
- Lang.Crucible.LLVM.Intrinsics.Libc: callCeil :: forall fi p sym bak ext r args ret. IsSymBackend sym bak => bak -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callCeil :: forall fi p sym ext r args ret. IsSymInterface sym => RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
- Lang.Crucible.LLVM.Intrinsics.Libc: callExit :: (IsSymBackend sym bak, ?intrinsicsOpts :: IntrinsicsOptions) => bak -> RegEntry sym (BVType 32) -> OverrideSim p sym ext r args ret (RegValue sym UnitType)
+ Lang.Crucible.LLVM.Intrinsics.Libc: callExit :: (IsSymInterface sym, ?intrinsicsOpts :: IntrinsicsOptions) => RegEntry sym (BVType 32) -> OverrideSim p sym ext r args ret (RegValue sym UnitType)
- Lang.Crucible.LLVM.Intrinsics.Libc: callFMA :: forall fi p sym bak ext r args ret. IsSymBackend sym bak => bak -> RegEntry sym (FloatType fi) -> RegEntry sym (FloatType fi) -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callFMA :: forall fi p sym ext r args ret. IsSymInterface sym => RegEntry sym (FloatType fi) -> RegEntry sym (FloatType fi) -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
- Lang.Crucible.LLVM.Intrinsics.Libc: callFloor :: forall fi p sym bak ext r args ret. IsSymBackend sym bak => bak -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callFloor :: forall fi p sym ext r args ret. IsSymInterface sym => RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
- Lang.Crucible.LLVM.Intrinsics.Libc: callFree :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr) => bak -> GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> OverrideSim p sym ext r args ret ()
+ Lang.Crucible.LLVM.Intrinsics.Libc: callFree :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> OverrideSim p sym ext r args ret ()
- Lang.Crucible.LLVM.Intrinsics.Libc: callIsinf :: forall fi w p sym bak ext r args ret. (IsSymBackend sym bak, 1 <= w) => bak -> NatRepr w -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callIsinf :: forall fi w p sym ext r args ret. (IsSymInterface sym, 1 <= w) => NatRepr w -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.Libc: callIsnan :: forall fi w p sym bak ext r args ret. (IsSymBackend sym bak, 1 <= w) => bak -> NatRepr w -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callIsnan :: forall fi w p sym ext r args ret. (IsSymInterface sym, 1 <= w) => NatRepr w -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.Libc: callLLVMAbs :: (1 <= w, IsSymBackend sym bak, HasLLVMAnn sym) => bak -> CallStack -> NatRepr w -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callLLVMAbs :: (1 <= w, IsSymInterface sym, HasLLVMAnn sym) => CallStack -> NatRepr w -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.Libc: callLibcAbs :: (1 <= w, IsSymBackend sym bak, HasLLVMAnn sym) => bak -> CallStack -> NatRepr w -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callLibcAbs :: (1 <= w, IsSymInterface sym, HasLLVMAnn sym) => CallStack -> NatRepr w -> RegEntry sym (BVType w) -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))
- Lang.Crucible.LLVM.Intrinsics.Libc: callMalloc :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> Alignment -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callMalloc :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => GlobalVar Mem -> Alignment -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))
- Lang.Crucible.LLVM.Intrinsics.Libc: callMemcpy :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret ()
+ Lang.Crucible.LLVM.Intrinsics.Libc: callMemcpy :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret ()
- Lang.Crucible.LLVM.Intrinsics.Libc: callMemmove :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret ()
+ Lang.Crucible.LLVM.Intrinsics.Libc: callMemmove :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret ()
- Lang.Crucible.LLVM.Intrinsics.Libc: callMemset :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr) => bak -> GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType 8) -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret ()
+ Lang.Crucible.LLVM.Intrinsics.Libc: callMemset :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType 8) -> RegEntry sym (BVType w) -> RegEntry sym (BVType 1) -> OverrideSim p sym ext r args ret ()
- Lang.Crucible.LLVM.Intrinsics.Libc: callPosixMemalign :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callPosixMemalign :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))
- Lang.Crucible.LLVM.Intrinsics.Libc: callPrintf :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (VectorType AnyType) -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callPrintf :: (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (VectorType AnyType) -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))
- Lang.Crucible.LLVM.Intrinsics.Libc: callPutChar :: IsSymBackend sym bak => bak -> GlobalVar Mem -> RegEntry sym (BVType 32) -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callPutChar :: IsSymInterface sym => GlobalVar Mem -> RegEntry sym (BVType 32) -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))
- Lang.Crucible.LLVM.Intrinsics.Libc: callPuts :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callPuts :: (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))
- Lang.Crucible.LLVM.Intrinsics.Libc: callRealloc :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> Alignment -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callRealloc :: (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => GlobalVar Mem -> Alignment -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))
- Lang.Crucible.LLVM.Intrinsics.Libc: callSpecialFunction1 :: forall fi p sym bak ext r args ret. (IsSymBackend sym bak, KnownRepr FloatInfoRepr fi) => bak -> SpecialFunction (EmptyCtx ::> R) -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callSpecialFunction1 :: forall fi p sym ext r args ret. (IsSymInterface sym, KnownRepr FloatInfoRepr fi) => SpecialFunction (EmptyCtx ::> R) -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
- Lang.Crucible.LLVM.Intrinsics.Libc: callSpecialFunction2 :: forall fi p sym bak ext r args ret. (IsSymBackend sym bak, KnownRepr FloatInfoRepr fi) => bak -> SpecialFunction ((EmptyCtx ::> R) ::> R) -> RegEntry sym (FloatType fi) -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callSpecialFunction2 :: forall fi p sym ext r args ret. (IsSymInterface sym, KnownRepr FloatInfoRepr fi) => SpecialFunction ((EmptyCtx ::> R) ::> R) -> RegEntry sym (FloatType fi) -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
- Lang.Crucible.LLVM.Intrinsics.Libc: callSqrt :: forall fi p sym bak ext r args ret. IsSymBackend sym bak => bak -> RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callSqrt :: forall fi p sym ext r args ret. IsSymInterface sym => RegEntry sym (FloatType fi) -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))
- Lang.Crucible.LLVM.Intrinsics.Libc: callStrlen :: (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (BVType wptr))
+ Lang.Crucible.LLVM.Intrinsics.Libc: callStrlen :: (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => GlobalVar Mem -> RegEntry sym (LLVMPointerType wptr) -> OverrideSim p sym ext r args ret (RegValue sym (BVType wptr))
- Lang.Crucible.LLVM.Intrinsics.Libc: cxa_atexitOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym (((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: cxa_atexitOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext (((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAbortOverride :: (IsSymInterface sym, ?intrinsicsOpts :: IntrinsicsOptions) => LLVMOverride p sym EmptyCtx UnitType
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAbortOverride :: (IsSymInterface sym, ?intrinsicsOpts :: IntrinsicsOptions) => LLVMOverride p sym ext EmptyCtx UnitType
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAbsOverride :: (IsSymInterface sym, HasLLVMAnn sym) => LLVMOverride p sym (EmptyCtx ::> BVType 32) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAbsOverride :: (IsSymInterface sym, HasLLVMAnn sym) => LLVMOverride p sym ext (EmptyCtx ::> BVType 32) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAcosOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAcosOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAcosfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAcosfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAcoshOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAcoshOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAcoshfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAcoshfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAsinOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAsinOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAsinfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAsinfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAsinhOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAsinhOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAsinhfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAsinhfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAssertFailOverride :: (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> LLVMPointerType wptr) UnitType
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAssertFailOverride :: (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> LLVMPointerType wptr) UnitType
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAssertRtnOverride :: (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> LLVMPointerType wptr) UnitType
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAssertRtnOverride :: (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType 32) ::> LLVMPointerType wptr) UnitType
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtan2Override :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtan2Override :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtan2fOverride :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtan2fOverride :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtanOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtanOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtanfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtanfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtanhOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtanhOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtanhfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmAtanhfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmCallocOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => LLVMOverride p sym ((EmptyCtx ::> BVType wptr) ::> BVType wptr) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmCallocOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((EmptyCtx ::> BVType wptr) ::> BVType wptr) (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmCeilOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmCeilOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmCeilfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmCeilfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmCosOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmCosOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmCosfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmCosfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmCoshOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmCoshOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmCoshfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmCoshfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmExitOverride :: forall sym p. (IsSymInterface sym, ?intrinsicsOpts :: IntrinsicsOptions) => LLVMOverride p sym (EmptyCtx ::> BVType 32) UnitType
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmExitOverride :: forall sym p ext. (IsSymInterface sym, ?intrinsicsOpts :: IntrinsicsOptions) => LLVMOverride p sym ext (EmptyCtx ::> BVType 32) UnitType
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmExp10Override :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmExp10Override :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmExp10fOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmExp10fOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmExp2Override :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmExp2Override :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmExp2fOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmExp2fOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmExpOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmExpOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmExpfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmExpfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmExpm1Override :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmExpm1Override :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmExpm1fOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmExpm1fOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmFloorOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmFloorOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmFloorfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmFloorfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmFmaOverride :: forall sym p. IsSymInterface sym => LLVMOverride p sym (((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmFmaOverride :: forall sym p ext. IsSymInterface sym => LLVMOverride p sym ext (((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmFmafOverride :: forall sym p. IsSymInterface sym => LLVMOverride p sym (((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmFmafOverride :: forall sym p ext. IsSymInterface sym => LLVMOverride p sym ext (((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmFreeOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr) UnitType
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmFreeOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr) UnitType
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmGetenvOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmGetenvOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr) (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmHtonlOverride :: (IsSymInterface sym, ?lc :: TypeContext) => LLVMOverride p sym (EmptyCtx ::> BVType 32) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmHtonlOverride :: (IsSymInterface sym, ?lc :: TypeContext) => LLVMOverride p sym ext (EmptyCtx ::> BVType 32) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmHtonsOverride :: (IsSymInterface sym, ?lc :: TypeContext) => LLVMOverride p sym (EmptyCtx ::> BVType 16) (BVType 16)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmHtonsOverride :: (IsSymInterface sym, ?lc :: TypeContext) => LLVMOverride p sym ext (EmptyCtx ::> BVType 16) (BVType 16)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmHypotOverride :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmHypotOverride :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmHypotfOverride :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmHypotfOverride :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmIsinfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmIsinfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmIsnanOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmIsnanOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmLAbsOverride_32 :: (IsSymInterface sym, HasLLVMAnn sym) => LLVMOverride p sym (EmptyCtx ::> BVType 32) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmLAbsOverride_32 :: (IsSymInterface sym, HasLLVMAnn sym) => LLVMOverride p sym ext (EmptyCtx ::> BVType 32) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmLAbsOverride_64 :: (IsSymInterface sym, HasLLVMAnn sym) => LLVMOverride p sym (EmptyCtx ::> BVType 64) (BVType 64)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmLAbsOverride_64 :: (IsSymInterface sym, HasLLVMAnn sym) => LLVMOverride p sym ext (EmptyCtx ::> BVType 64) (BVType 64)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmLLAbsOverride :: (IsSymInterface sym, HasLLVMAnn sym) => LLVMOverride p sym (EmptyCtx ::> BVType 64) (BVType 64)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmLLAbsOverride :: (IsSymInterface sym, HasLLVMAnn sym) => LLVMOverride p sym ext (EmptyCtx ::> BVType 64) (BVType 64)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog10Override :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog10Override :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog10fOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog10fOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog1pOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog1pOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog1pfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog1pfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog2Override :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog2Override :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog2fOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmLog2fOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmLogOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmLogOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmLogfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmLogfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmMallocOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => LLVMOverride p sym (EmptyCtx ::> BVType wptr) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmMallocOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => LLVMOverride p sym ext (EmptyCtx ::> BVType wptr) (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmMemcpyChkOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType wptr) ::> BVType wptr) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmMemcpyChkOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType wptr) ::> BVType wptr) (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmMemcpyOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym (((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType wptr) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmMemcpyOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext (((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType wptr) (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmMemmoveOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym (((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType wptr) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmMemmoveOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext (((EmptyCtx ::> LLVMPointerType wptr) ::> LLVMPointerType wptr) ::> BVType wptr) (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmMemsetChkOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType wptr) ::> BVType wptr) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmMemsetChkOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ext ((((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType wptr) ::> BVType wptr) (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmMemsetOverride :: forall p sym wptr. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType wptr) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmMemsetOverride :: forall p sym ext wptr. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMOverride p sym ext (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) ::> BVType wptr) (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmNtohlOverride :: (IsSymInterface sym, ?lc :: TypeContext) => LLVMOverride p sym (EmptyCtx ::> BVType 32) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmNtohlOverride :: (IsSymInterface sym, ?lc :: TypeContext) => LLVMOverride p sym ext (EmptyCtx ::> BVType 32) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmNtohsOverride :: (IsSymInterface sym, ?lc :: TypeContext) => LLVMOverride p sym (EmptyCtx ::> BVType 16) (BVType 16)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmNtohsOverride :: (IsSymInterface sym, ?lc :: TypeContext) => LLVMOverride p sym ext (EmptyCtx ::> BVType 16) (BVType 16)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmPowOverride :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmPowOverride :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType DoubleFloat) ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmPowfOverride :: IsSymInterface sym => LLVMOverride p sym ((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmPowfOverride :: IsSymInterface sym => LLVMOverride p sym ext ((EmptyCtx ::> FloatType SingleFloat) ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmPrintfChkOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym (((EmptyCtx ::> BVType 32) ::> LLVMPointerType wptr) ::> VectorType AnyType) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmPrintfChkOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext (((EmptyCtx ::> BVType 32) ::> LLVMPointerType wptr) ::> VectorType AnyType) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmPrintfOverride :: (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => LLVMOverride p sym ((EmptyCtx ::> LLVMPointerType wptr) ::> VectorType AnyType) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmPrintfOverride :: (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((EmptyCtx ::> LLVMPointerType wptr) ::> VectorType AnyType) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmPutCharOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym (EmptyCtx ::> BVType 32) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmPutCharOverride :: (IsSymInterface sym, HasPtrWidth wptr) => LLVMOverride p sym ext (EmptyCtx ::> BVType 32) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmPutsOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmPutsOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmReallocOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => LLVMOverride p sym ((EmptyCtx ::> LLVMPointerType wptr) ::> BVType wptr) (LLVMPointerType wptr)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmReallocOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => LLVMOverride p sym ext ((EmptyCtx ::> LLVMPointerType wptr) ::> BVType wptr) (LLVMPointerType wptr)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmSinOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmSinOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmSinfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmSinfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmSinhOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmSinhOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmSinhfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmSinhfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmSqrtOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmSqrtOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmSqrtfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmSqrtfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmStrlenOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr) (BVType wptr)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmStrlenOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr) (BVType wptr)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmTanOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmTanOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmTanfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmTanfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmTanhOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmTanhOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (FloatType DoubleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvmTanhfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvmTanhfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (FloatType SingleFloat)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvm__isinfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvm__isinfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvm__isinffOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvm__isinffOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvm__isnanOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType DoubleFloat) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvm__isnanOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType DoubleFloat) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: llvm__isnanfOverride :: IsSymInterface sym => LLVMOverride p sym (EmptyCtx ::> FloatType SingleFloat) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: llvm__isnanfOverride :: IsSymInterface sym => LLVMOverride p sym ext (EmptyCtx ::> FloatType SingleFloat) (BVType 32)
- Lang.Crucible.LLVM.Intrinsics.Libc: posixMemalignOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => LLVMOverride p sym (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType wptr) ::> BVType wptr) (BVType 32)
+ Lang.Crucible.LLVM.Intrinsics.Libc: posixMemalignOverride :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?lc :: TypeContext, ?memOpts :: MemOptions) => LLVMOverride p sym ext (((EmptyCtx ::> LLVMPointerType wptr) ::> BVType wptr) ::> BVType wptr) (BVType 32)
- Lang.Crucible.LLVM.MemModel: MemOptions :: !Bool -> !Bool -> !Bool -> IndeterminateLoadBehavior -> MemOptions
+ Lang.Crucible.LLVM.MemModel: MemOptions :: !Bool -> !Bool -> !Bool -> IndeterminateLoadBehavior -> !Bool -> MemOptions
- Lang.Crucible.LLVM.MemModel.MemLog: Mem :: EndianForm -> MemState sym -> Mem sym
+ Lang.Crucible.LLVM.MemModel.MemLog: Mem :: EndianForm -> MemState sym -> Set Natural -> Mem sym
- Lang.Crucible.LLVM.SymIO: callCloseFile :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr) => bak -> GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (BVType 32) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType 32))
+ Lang.Crucible.LLVM.SymIO: callCloseFile :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (BVType 32) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType 32))
- Lang.Crucible.LLVM.SymIO: callOpenFile :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType 32) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType 32))
+ Lang.Crucible.LLVM.SymIO: callOpenFile :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType 32) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType 32))
- Lang.Crucible.LLVM.SymIO: callReadFileHandle :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr) => bak -> GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (BVType 32) -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType wptr))
+ Lang.Crucible.LLVM.SymIO: callReadFileHandle :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (BVType 32) -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType wptr))
- Lang.Crucible.LLVM.SymIO: callWriteFileHandle :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => bak -> GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (BVType 32) -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType wptr))
+ Lang.Crucible.LLVM.SymIO: callWriteFileHandle :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (BVType 32) -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType wptr))
- Lang.Crucible.LLVM.SymIO: closeFile :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMFileSystem wptr -> LLVMOverride p sym (EmptyCtx ::> BVType 32) (BVType 32)
+ Lang.Crucible.LLVM.SymIO: closeFile :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMFileSystem wptr -> LLVMOverride p sym ext (EmptyCtx ::> BVType 32) (BVType 32)
- Lang.Crucible.LLVM.SymIO: openFile :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMFileSystem wptr -> LLVMOverride p sym ((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) (BVType 32)
+ Lang.Crucible.LLVM.SymIO: openFile :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMFileSystem wptr -> LLVMOverride p sym ext ((EmptyCtx ::> LLVMPointerType wptr) ::> BVType 32) (BVType 32)
- Lang.Crucible.LLVM.SymIO: readFileHandle :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMFileSystem wptr -> LLVMOverride p sym (((EmptyCtx ::> BVType 32) ::> LLVMPointerType wptr) ::> BVType wptr) (BVType wptr)
+ Lang.Crucible.LLVM.SymIO: readFileHandle :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMFileSystem wptr -> LLVMOverride p sym ext (((EmptyCtx ::> BVType 32) ::> LLVMPointerType wptr) ::> BVType wptr) (BVType wptr)
- Lang.Crucible.LLVM.SymIO: symio_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch, ?memOpts :: MemOptions) => LLVMFileSystem wptr -> [OverrideTemplate p sym arch rtp l a]
+ Lang.Crucible.LLVM.SymIO: symio_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch, ?memOpts :: MemOptions) => LLVMFileSystem wptr -> [OverrideTemplate p sym ext arch]
- Lang.Crucible.LLVM.SymIO: writeFileHandle :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMFileSystem wptr -> LLVMOverride p sym (((EmptyCtx ::> BVType 32) ::> LLVMPointerType wptr) ::> BVType wptr) (BVType wptr)
+ Lang.Crucible.LLVM.SymIO: writeFileHandle :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMFileSystem wptr -> LLVMOverride p sym ext (((EmptyCtx ::> BVType 32) ::> LLVMPointerType wptr) ::> BVType wptr) (BVType wptr)
Files
- CHANGELOG.md +26/−0
- crucible-llvm.cabal +6/−2
- src/Lang/Crucible/LLVM.hs +10/−8
- src/Lang/Crucible/LLVM/Functions.hs +277/−0
- src/Lang/Crucible/LLVM/Globals.hs +256/−59
- src/Lang/Crucible/LLVM/Intrinsics.hs +75/−281
- src/Lang/Crucible/LLVM/Intrinsics/Cast.hs +133/−0
- src/Lang/Crucible/LLVM/Intrinsics/Common.hs +174/−180
- src/Lang/Crucible/LLVM/Intrinsics/LLVM.hs +2089/−1520
- src/Lang/Crucible/LLVM/Intrinsics/Libc.hs +1794/−1653
- src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs +15/−17
- src/Lang/Crucible/LLVM/Intrinsics/Match.hs +109/−0
- src/Lang/Crucible/LLVM/Intrinsics/Options.hs +3/−3
- src/Lang/Crucible/LLVM/MemModel.hs +64/−74
- src/Lang/Crucible/LLVM/MemModel/Generic.hs +136/−56
- src/Lang/Crucible/LLVM/MemModel/MemLog.hs +28/−14
- src/Lang/Crucible/LLVM/MemModel/Options.hs +8/−0
- src/Lang/Crucible/LLVM/MemModel/Partial.hs +26/−9
- src/Lang/Crucible/LLVM/MemModel/Pointer.hs +126/−6
- src/Lang/Crucible/LLVM/MemModel/Value.hs +2/−2
- src/Lang/Crucible/LLVM/Printf.hs +9/−1
- src/Lang/Crucible/LLVM/QQ.hs +19/−5
- src/Lang/Crucible/LLVM/SimpleLoopFixpointCHC.hs +1421/−0
- src/Lang/Crucible/LLVM/SimpleLoopInvariant.hs +1/−1
- src/Lang/Crucible/LLVM/SymIO.hs +30/−32
- src/Lang/Crucible/LLVM/Translation/Expr.hs +0/−1
- src/Lang/Crucible/LLVM/Translation/Instruction.hs +125/−12
- src/Lang/Crucible/LLVM/Utils.hs +31/−1
- test/TestMemory.hs +3/−3
CHANGELOG.md view
@@ -1,3 +1,29 @@+# 0.7 -- 2024-08-30++* Add support for GHC 9.8+* Add integer-related `llvm.vector.reduce.*` intrinsics.+* Add workaround to allow loading bitcode using LLVM's reltable lookup optimization.+* `register_llvm_overrides{,_}` now returns the list of overrides that were+ applied.+* The `doMallocHandle` function was removed.+* The `RegOverrideM` monad was replaced by the `MakeOverride` function newtype.+* Several type parameters were removed from `OverrideTemplate`, and the `ext`+ parameter was added. This had downstream effects in `basic_llvm_override`,+ `polymorphic1_llvm_override`, and other functions for registering overrides.+* Override registration code was generalized. `bind_llvm_{handle,func}`+ now don't require a whole `LLVMContext`, just a `GlobalVar Mem`, and are+ polymorphic over `ext`.+* `build_llvm_override` is now generic over the `ext` type parameter. This+ should be a backwards-compatible change.+* `LLVMOverride` now has an additional `ext` type parameter. See the Haddocks+ for `LLVMOverride` for details and motivation.+* The `llvmOverride_def` field of `LLVMOverride` no longer takes a `bak`+ argument. To retrieve the current symbolic backend, use+ `Lang.Crucible.Simulator.OverrideSim.ovrWithBackend`.+* Add overrides for integer-related `llvm.vector.reduce.*` intrinsics.+* Add support for atomic `fadd`, `fsub`, `fmax`, `fmin`, `uinc_wrap`, and+ `udec_wrap` operations in `atomicrmw` instructions.+ # 0.6 -- 2024-02-05 * `bindLLVMFunPtr` now accepts an `Text.LLVM.AST.Symbol` rather than a whole `Declare`.
crucible-llvm.cabal view
@@ -1,6 +1,6 @@ Cabal-version: 2.2 Name: crucible-llvm-Version: 0.6+Version: 0.7 Author: Galois Inc. Copyright: (c) Galois, Inc 2014-2022 Maintainer: rscott@galois.com, kquick@galois.com, langston@galois.com@@ -33,7 +33,7 @@ library import: bldflags build-depends:- base >= 4.13 && < 4.19,+ base >= 4.13 && < 4.20, attoparsec, bv-sized >= 1.0.0, bytestring,@@ -71,8 +71,10 @@ Lang.Crucible.LLVM.Errors.UndefinedBehavior Lang.Crucible.LLVM.Eval Lang.Crucible.LLVM.Extension+ Lang.Crucible.LLVM.Functions Lang.Crucible.LLVM.Globals Lang.Crucible.LLVM.Intrinsics+ Lang.Crucible.LLVM.Intrinsics.Cast Lang.Crucible.LLVM.Intrinsics.Libc Lang.Crucible.LLVM.Intrinsics.LLVM Lang.Crucible.LLVM.MalformedLLVMModule@@ -89,6 +91,7 @@ Lang.Crucible.LLVM.QQ Lang.Crucible.LLVM.SymIO Lang.Crucible.LLVM.SimpleLoopFixpoint+ Lang.Crucible.LLVM.SimpleLoopFixpointCHC Lang.Crucible.LLVM.SimpleLoopInvariant Lang.Crucible.LLVM.Translation Lang.Crucible.LLVM.Translation.Aliases@@ -100,6 +103,7 @@ Lang.Crucible.LLVM.Extension.Syntax Lang.Crucible.LLVM.Intrinsics.Common Lang.Crucible.LLVM.Intrinsics.Libcxx+ Lang.Crucible.LLVM.Intrinsics.Match Lang.Crucible.LLVM.Intrinsics.Options Lang.Crucible.LLVM.MemModel.Common Lang.Crucible.LLVM.MemModel.Options
src/Lang/Crucible/LLVM.hs view
@@ -40,6 +40,7 @@ import Lang.Crucible.LLVM.Eval (llvmExtensionEval) import Lang.Crucible.Panic (panic) import Lang.Crucible.LLVM.Extension (ArchWidth)+import Lang.Crucible.LLVM.Functions (bindLLVMHandle, bindLLVMCFG) import Lang.Crucible.LLVM.Intrinsics import Lang.Crucible.LLVM.MemModel ( llvmStatementExec, HasPtrWidth, HasLLVMAnn, MemOptions, MemImpl@@ -84,12 +85,12 @@ , show sym ] Just (decl, AnyCFG cfg, warns) -> do- let h = cfgHandle cfg- s = UseCFG cfg (postdomInfo cfg)- binds <- use (stateContext . functionBindings) let llvmCtx = mtrans ^. transContext- bind_llvm_handle llvmCtx (L.decName decl) h s+ let mvar = llvmMemVar llvmCtx+ bindLLVMCFG mvar (L.decName decl) cfg + binds <- use (stateContext . functionBindings)+ let h = cfgHandle cfg when (isJust $ lookupHandleMap h $ fnBindings binds) $ do loc <- liftIO . getCurrentProgramLoc =<< getSymInterface liftIO (handleWarning (LLVMTranslationWarning sym (plSourceLoc loc) "LLVM function handle registered twice"))@@ -127,7 +128,9 @@ , show sym ] Just (decl, SomeHandle h) ->- do -- Bind the function handle we just created to the following bootstrapping code,+ do let llvmCtx = mtrans ^. transContext+ let mvar = llvmMemVar llvmCtx+ -- Bind the function handle we just created to the following bootstrapping code, -- which actually translates the function on its first execution and patches up -- behind itself. let s =@@ -150,14 +153,13 @@ Just Refl -> do liftIO $ mapM_ handleWarning warns -- Here we rebind the function handle to use the translated CFG- bindFnHandle h (UseCFG cfg (postdomInfo cfg))+ bindLLVMHandle mvar (L.decName decl) h (UseCFG cfg (postdomInfo cfg)) -- Now, make recursive call to ourself, which should invoke the -- newly-installed CFG regValue <$> (callFnVal (HandleFnVal h) =<< getOverrideArgs) -- Bind the function handle to the appropriate global symbol.- let llvmCtx = mtrans ^. transContext- bind_llvm_handle llvmCtx (L.decName decl) h s+ bindLLVMHandle mvar (L.decName decl) h s llvmGlobalsToCtx
+ src/Lang/Crucible/LLVM/Functions.hs view
@@ -0,0 +1,277 @@+-- |+-- Module : Lang.Crucible.LLVM.Functions+-- Description : Register functions (CFGs and overrides)+-- Copyright : (c) Galois, Inc 2024+-- License : BSD3+-- Maintainer : Langston Barrett <langston@galois.com>+-- Stability : provisional+--+-- Registering functions to be used with the LLVM memory model is somewhat more+-- complex than for other Crucible frontends, as LLVM has a notion of function+-- pointers. Each function to be registered has to go through a few steps (the+-- first two are common to all Crucible frontends):+--+-- * Create a 'FnHandle' and a 'FnState' (a translated CFG or an override)+-- * Bind the 'FnHandle' to the 'FnState' ('OverrideSim.bindFnHandle')+-- * Create a (global, immutable, zero-sized) allocation corresponding to the+-- function in the 'MemImpl' ('allocFunPtr')+-- * Register the correspondence between the function\'s name (and any aliases)+-- and its global allocation ('registerGlobal', or via 'registerFunPtr')+-- * Register the correspondence between the function\'s allocation and its+-- handle ('doInstallHandle', or via 'bindLLVMHandle', 'bindLLVMCFG', or+-- 'bindLLVMFunc')+--+-- This module provides helpers to accomplish all of this. They\'re ordered+-- roughly low-level/customizable to high-level/automated.+--+-- Perhaps surprisingly, there\'s no function that does all of the above at+-- once. This is because there are two main places where binding functions+-- happens:+--+-- * "Lang.Crucible.LLVM" registers translated CFGs, but does so lazily. In+-- particular, this means that it initially binds the handle and allocation to+-- a \"stub\" that, when called, will translate the actual CFG and then+-- re-bind the handle and allocation to it.+-- * "Lang.Crucible.LLVM.Intrinsics.Common" registers overrides, which generally+-- apply to functions that are @declare@d but not @define@d. Thus, they+-- already have corresponding allocations, which just need to be associated+-- with the override.+--+-- Prior to these, function allocation happens in+-- 'Lang.Crucible.LLVM.Globals.initializeMemory'.+------------------------------------------------------------------------++{-# LANGUAGE GADTs #-}+{-# LANGUAGE ImplicitParams #-}++module Lang.Crucible.LLVM.Functions+ ( allocFunPtr+ , allocLLVMFunPtr+ , allocLLVMFunPtrs+ , registerFunPtr+ , bindLLVMFunPtr+ , bindLLVMHandle+ , bindLLVMCFG+ , bindLLVMFunc+ ) where++import Control.Lens (use)+import Control.Monad (foldM)+import Control.Monad.IO.Class (liftIO)+import qualified Data.Map as Map+import qualified Data.Set as Set+import qualified Data.Text as Text++import qualified Text.LLVM.AST as L++import qualified Data.Parameterized.Context as Ctx++import What4.FunctionName (functionNameFromText)+import qualified What4.Interface as W4++import Lang.Crucible.Analysis.Postdom (postdomInfo)+import Lang.Crucible.Backend+import Lang.Crucible.CFG.Common (GlobalVar)+import Lang.Crucible.CFG.Core (CFG)+import Lang.Crucible.CFG.Core (TypeRepr(..), cfgHandle)+import Lang.Crucible.FunctionHandle (FnHandle(handleArgTypes), mkHandle')+import Lang.Crucible.Simulator.ExecutionTree (stateContext)+import Lang.Crucible.Simulator (FnState(..), SimContext(..))+import Lang.Crucible.Simulator.OverrideSim (OverrideSim)+import qualified Lang.Crucible.Simulator.OverrideSim as OverrideSim++import Lang.Crucible.LLVM.DataLayout+import Lang.Crucible.LLVM.MemModel+import qualified Lang.Crucible.LLVM.MemModel as G+import Lang.Crucible.LLVM.Translation.Monad+import Lang.Crucible.LLVM.Extension (LLVM)++-- | Create a global allocation to be assocated with a function.+--+-- The returned allocation is global ('G.GlobalAlloc'), immutable+-- ('G.Immutable'), and has a size and alignment of zero.+allocFunPtr ::+ ( IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym+ , ?memOpts :: MemOptions ) =>+ bak ->+ MemImpl sym ->+ -- | Function Name+ String ->+ IO (LLVMPtr sym wptr, MemImpl sym)+allocFunPtr bak mem nm = do+ let sym = backendGetSym bak+ z <- W4.bvZero sym ?ptrWidth+ doMalloc bak G.GlobalAlloc G.Immutable nm mem z noAlignment++-- | Create a global allocation assocated with a function (see 'allocFunPtr'),+-- and register the function\'s primary symbol and its aliases as associated+-- with that allocation.+registerFunPtr ::+ ( IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym+ , ?memOpts :: MemOptions ) =>+ bak ->+ MemImpl sym ->+ -- | Display name+ String ->+ -- | Function name+ L.Symbol ->+ -- | Aliases+ [L.Symbol] ->+ IO (LLVMPtr sym wptr, MemImpl sym)+registerFunPtr bak mem displayName nm aliases = do+ (ptr, mem') <- allocFunPtr bak mem displayName+ return $ (ptr, registerGlobal mem' (nm:aliases) ptr)++-- Not exported+funAliases ::+ LLVMContext arch ->+ L.Symbol ->+ [L.Symbol]+funAliases llvmCtx symbol =+ let aliases = llvmFunctionAliases llvmCtx+ in map L.aliasName $ maybe [] Set.toList $ Map.lookup symbol aliases++-- | Create a global allocation assocated with a function (see 'allocFunPtr'),+-- register the function\'s primary symbol and its aliases as associated with+-- that allocation (see 'registerFunPtr'), looking up the aliases from the+-- 'LLVMContext'.+allocLLVMFunPtr ::+ ( IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym+ , ?memOpts :: MemOptions ) =>+ bak ->+ LLVMContext arch ->+ MemImpl sym ->+ Either L.Declare L.Define ->+ IO (LLVMPtr sym wptr, MemImpl sym)+allocLLVMFunPtr bak llvm_ctx mem decl = do+ let (symbol, displayString) =+ case decl of+ Left d ->+ let s@(L.Symbol nm) = L.decName d+ in ( s, "[external function] " ++ nm )+ Right d ->+ let s@(L.Symbol nm) = L.defName d+ in ( s, "[defined function ] " ++ nm)+ let aliases = funAliases llvm_ctx symbol+ registerFunPtr bak mem displayString symbol aliases++-- | Create global allocations associated with each function in a module (see+-- 'allocLLVMFunPtr').+allocLLVMFunPtrs ::+ ( IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym+ , ?memOpts :: MemOptions ) =>+ bak ->+ LLVMContext arch ->+ MemImpl sym ->+ L.Module ->+ IO (MemImpl sym)+allocLLVMFunPtrs bak llvmCtx mem0 llvmMod = do+ -- allocate pointers values for function symbols, but do not+ -- yet bind them to function handles+ let decls = map Left (L.modDeclares llvmMod) ++ map Right (L.modDefines llvmMod)++ let allocLLVMFunPtr' bak' lctx mem decl = snd <$> allocLLVMFunPtr bak' lctx mem decl+ foldM (allocLLVMFunPtr' bak llvmCtx) mem0 decls++-- Not exported+someFnHandle :: FnHandle args ret -> SomeFnHandle+someFnHandle h =+ case handleArgTypes h of+ (_ Ctx.:> VectorRepr AnyRepr) -> VarargsFnHandle h+ _ -> SomeFnHandle h++-- | Look up an existing global function allocation by name and bind a handle+-- to it.+--+-- This can overwrite existing allocation/handle associations, and is used to do+-- so when registering lazily-translated CFGs.+--+-- For a stateful version in 'OverrideSim', see 'bindLLVMHandle'.+bindLLVMFunPtr ::+ (IsSymBackend sym bak, HasPtrWidth wptr) =>+ bak ->+ -- | Function name+ L.Symbol ->+ -- | Function implementation (CFG or override)+ FnHandle args ret ->+ -- | LLVM memory+ MemImpl sym ->+ IO (MemImpl sym)+bindLLVMFunPtr bak nm h mem = do+ ptr <- doResolveGlobal bak mem nm+ doInstallHandle bak ptr (someFnHandle h) mem++-- | Look up an existing global function allocation by name and bind a handle+-- to it.+--+-- This can overwrite existing allocation/handle associations, and is used to do+-- so when registering lazily-translated CFGs.+--+-- For a less stateful version in 'IO', see 'bindLLVMHandle'.+bindLLVMHandle ::+ (IsSymInterface sym, HasPtrWidth wptr) =>+ GlobalVar Mem ->+ -- | Function name+ L.Symbol ->+ -- | Function handle+ FnHandle args ret ->+ -- | Function implementation (CFG or override)+ FnState p sym ext args ret ->+ OverrideSim p sym ext rtp l a ()+bindLLVMHandle mvar nm hdl impl = do+ OverrideSim.bindFnHandle hdl impl+ mem <- OverrideSim.readGlobal mvar+ mem' <- OverrideSim.ovrWithBackend $ \bak ->+ liftIO (bindLLVMFunPtr bak nm hdl mem)+ OverrideSim.writeGlobal mvar mem'++-- | Look up an existing global function allocation by name and bind a CFG to+-- it.+--+-- This can overwrite existing allocation/handle associations, and is used to do+-- so when registering lazily-translated CFGs.+bindLLVMCFG ::+ (IsSymInterface sym, HasPtrWidth wptr) =>+ GlobalVar Mem ->+ -- | Function name+ L.Symbol ->+ -- | Function CFG+ CFG LLVM blocks init ret ->+ OverrideSim p sym LLVM rtp l a ()+bindLLVMCFG mvar name cfg = do+ let h = cfgHandle cfg+ s = UseCFG cfg (postdomInfo cfg)+ bindLLVMHandle mvar name h s++-- Private helper to make function handles+mkHandle ::+ -- | Function name+ L.Symbol ->+ -- | Argument types+ Ctx.Assignment TypeRepr args ->+ -- | Return type+ TypeRepr ret ->+ OverrideSim p sym ext rtp l a (FnHandle args ret)+mkHandle nm args ret = do+ let L.Symbol strNm = nm+ let fnm = functionNameFromText (Text.pack strNm)+ ctx <- use stateContext+ let ha = simHandleAllocator ctx+ liftIO $ mkHandle' ha fnm args ret++-- | Create a function handle, then call 'bindLLVMHandle' on it.+bindLLVMFunc ::+ (IsSymInterface sym, HasPtrWidth wptr) =>+ GlobalVar Mem ->+ -- | Function name+ L.Symbol ->+ -- | Argument types+ Ctx.Assignment TypeRepr args ->+ -- | Return type+ TypeRepr ret ->+ -- | Function implementation (CFG or override)+ FnState p sym ext args ret ->+ OverrideSim p sym ext rtp l a ()+bindLLVMFunc mvar nm args ret impl = do+ hdl <- mkHandle nm args ret+ bindLLVMHandle mvar nm hdl impl
src/Lang/Crucible/LLVM/Globals.hs view
@@ -36,7 +36,6 @@ , populateGlobals , populateAllGlobals , populateConstGlobals- , registerFunPtr , GlobalInitializerMap , makeGlobalMap@@ -47,7 +46,7 @@ import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Except (MonadError(..)) import Control.Lens hiding (op, (:>) )-import Data.List (foldl')+import Data.List (foldl', genericLength, isPrefixOf) import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map import qualified Data.Set as Set@@ -58,14 +57,13 @@ import qualified Text.LLVM.AST as L -import qualified Data.BitVector.Sized as BV import Data.Parameterized.NatRepr as NatRepr import Lang.Crucible.LLVM.Bytes import Lang.Crucible.LLVM.DataLayout+import Lang.Crucible.LLVM.Functions (allocLLVMFunPtrs) import Lang.Crucible.LLVM.MemType import Lang.Crucible.LLVM.MemModel-import qualified Lang.Crucible.LLVM.MemModel.Generic as G import qualified Lang.Crucible.LLVM.PrettyPrint as LPP import Lang.Crucible.LLVM.Translation.Constant import Lang.Crucible.LLVM.Translation.Monad@@ -109,7 +107,7 @@ => LLVMContext arch -> L.Module -> GlobalInitializerMap-makeGlobalMap ctx m = foldl' addAliases globalMap (Map.toList (llvmGlobalAliases ctx))+makeGlobalMap ctx m = foldl' addAliases globalMap1 (Map.toList (llvmGlobalAliases ctx)) where addAliases mp (glob, aliases) =@@ -117,8 +115,9 @@ Just initzr -> insertAll (map L.aliasName (Set.toList aliases)) initzr mp Nothing -> mp -- should this be an error/exception? - globalMap = Map.fromList $ map (L.globalSym &&& (id &&& globalToConst))- (L.modGlobals m)+ globalMap0 = Map.fromList $ map (\g -> (L.globalSym g, g)) (L.modGlobals m)+ globalMap1 = Map.map (id &&& globalToConst) globalMap0+ loadRelConstInitMap = buildLoadRelConstInitMap globalMap0 m insertAll ks v mp = foldr (flip Map.insert v) mp ks @@ -137,11 +136,20 @@ => L.Global -> m (MemType, Maybe LLVMConst) globalToConst' g = do let ?lc = ctx^.llvmTypeCtx -- implicitly passed to transConstant- let gty = L.globalType g- let gval = L.globalValue g- mt <- liftMemType gty- val <- traverse (transConstant' mt) gval- return (mt, val)+ let (gty, mbGval) =+ -- Check if a global variable was passed as an argument to+ -- llvm.load.relative.i* (i.e., if it is reltable-like), and if+ -- so, use an altered value for the constant initializer that uses+ -- `bitcast`. See+ -- Note [Undoing LLVM's relative table lookup conversion pass].+ case Map.lookup (L.globalSym g) loadRelConstInitMap of+ Just (L.Typed constInitTy constInitVal) ->+ (constInitTy, Just constInitVal)+ Nothing ->+ (L.globalType g, L.globalValue g)+ mt <- liftMemType gty+ mbVal <- traverse (transConstant' mt) mbGval+ return (mt, mbVal) ------------------------------------------------------------------------- -- initializeMemory@@ -182,19 +190,39 @@ let endianness = dl^.intLayout mem0 <- emptyMem endianness - -- allocate pointers values for function symbols, but do not- -- yet bind them to function handles- let decls = map Left (L.modDeclares llvmModl) ++ map Right (L.modDefines llvmModl)- mem <- foldM (allocLLVMFunPtr bak llvm_ctx) mem0 decls+ -- allocate pointers values for function symbols, but do not yet bind them to+ -- function handles+ mem <- allocLLVMFunPtrs bak llvm_ctx mem0 llvmModl -- Allocate global values let globAliases = llvmGlobalAliases llvm_ctx let globals = L.modGlobals llvmModl+ let globalMap = Map.fromList $ map (\g -> (L.globalSym g, g)) globals+ let loadRelConstInitMap = buildLoadRelConstInitMap globalMap llvmModl gs_alloc <- mapM (\g -> do let err msg = malformedLLVMModule ("Invalid type for global" <> fromString (show (L.globalSym g))) [fromString msg]- ty <- either err return $ liftMemType $ L.globalType g+ -- Check if a global variable was passed as an argument+ -- to llvm.load.relative.i* (i.e., if it is+ -- reltable-like), and if so, use an altered type that+ -- uses pointers instead of `i32`s. Also, do not use the+ -- original global's alignment. See+ -- Note [Undoing LLVM's relative table lookup conversion pass].+ (ty, mbGlobAlign) <-+ case Map.lookup (L.globalSym g) loadRelConstInitMap of+ Just constInit -> do+ ty <- either err return $+ liftMemType $+ L.typedType constInit+ -- Return Nothing for the alignment so that we+ -- will instead use crucible-llvm's alignment+ -- inference to compute the alignment of the+ -- new constant initializer.+ pure (ty, Nothing)+ Nothing -> do+ ty <- either err return $ liftMemType $ L.globalType g+ pure (ty, L.globalAlign g) let sz = memTypeSize dl ty let tyAlign = memTypeAlign dl ty let aliases = map L.aliasName . Set.toList $@@ -210,7 +238,7 @@ -- specified, the global is forced to have -- exactly that alignment. alignment <-- case L.globalAlign g of+ case mbGlobAlign of Just a | a > 0 -> case toAlignment (toBytes a) of Nothing -> fail $ "Invalid alignemnt: " ++ show a ++ "\n " ++@@ -222,47 +250,6 @@ allocGlobals bak (filter (\(g, _, _, _) -> predicate g) gs_alloc) mem -allocLLVMFunPtr ::- ( IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym- , ?memOpts :: MemOptions ) =>- bak ->- LLVMContext arch ->- MemImpl sym ->- Either L.Declare L.Define ->- IO (MemImpl sym)-allocLLVMFunPtr bak llvm_ctx mem decl =- do let (symbol, displayString) =- case decl of- Left d ->- let s@(L.Symbol nm) = L.decName d- in ( s, "[external function] " ++ nm )- Right d ->- let s@(L.Symbol nm) = L.defName d- in ( s, "[defined function ] " ++ nm)- let funAliases = llvmFunctionAliases llvm_ctx- let aliases = map L.aliasName $ maybe [] Set.toList $ Map.lookup symbol funAliases- (_ptr, mem') <- registerFunPtr bak mem displayString symbol aliases- return mem'---- | Create a global allocation assocated with a function-registerFunPtr ::- ( IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym- , ?memOpts :: MemOptions ) =>- bak ->- MemImpl sym ->- -- | Display name- String ->- -- | Function name- L.Symbol ->- -- | Aliases- [L.Symbol] ->- IO (LLVMPtr sym wptr, MemImpl sym)-registerFunPtr bak mem displayName nm aliases = do- let sym = backendGetSym bak- z <- bvLit sym ?ptrWidth (BV.zero ?ptrWidth)- (ptr, mem') <- doMalloc bak G.GlobalAlloc G.Immutable displayName mem z noAlignment- return $ (ptr, registerGlobal mem' (nm:aliases) ptr)- ------------------------------------------------------------------------ -- ** populateGlobals @@ -418,3 +405,213 @@ ptr <- doResolveGlobal bak mem (L.globalSym gl) (val, mem') <- runStateT (constToLLVMValP sym populateRec cval) mem storeConstRaw bak mem' ptr ty alignment val++------------------------------------------------------------------------+-- ** llvm.load.relative constant initializers++-- | A map of global variable names ('L.Symbol's) that appear as arguments to+-- calls to the @llvm.load.relative.i*@ intrinsic. See+-- @Note [Undoing LLVM's relative table lookup conversion pass]@ for why we need+-- this.+type LoadRelConstInitMap = Map L.Symbol (L.Typed L.Value)++-- | @buildLoadRelConstInitMap globalMap m@ takes a 'L.Module' (@m@) and a map+-- of global variable symbols to their definitions (@globalMap@) and computes+-- a 'LoadRelConstInitMap'. See+-- @Note [Undoing LLVM's relative table lookup conversion pass]@ for why we need+-- to do this.+buildLoadRelConstInitMap ::+ Map L.Symbol L.Global ->+ L.Module ->+ LoadRelConstInitMap+buildLoadRelConstInitMap globalMap m = foldMap defineConstInits (L.modDefines m)+ where+ defineConstInits :: L.Define -> LoadRelConstInitMap+ defineConstInits def = foldMap basicBlockConstInits (L.defBody def)++ basicBlockConstInits :: L.BasicBlock -> LoadRelConstInitMap+ basicBlockConstInits bb = foldMap stmtConstInits (L.bbStmts bb)++ stmtConstInits :: L.Stmt -> LoadRelConstInitMap+ stmtConstInits (L.Result _ instr _) = instrConstInits instr+ stmtConstInits (L.Effect instr _) = instrConstInits instr++ instrConstInits :: L.Instr -> LoadRelConstInitMap+ instrConstInits (L.Call _ _ (L.ValSymbol fun) [ptr, _offset])+ | L.Symbol funStr <- fun+ , "llvm.load.relative.i" `isPrefixOf` funStr+ , Just (gs, foldedConstTy, foldedConstInit) <-+ foldLoadRelConstInit (L.typedValue ptr)+ = Map.singleton gs (L.Typed foldedConstTy foldedConstInit)+ instrConstInits _ =+ Map.empty++ -- Check if the first argument to a call to llvm.load.relative.i* is+ -- "reltable-like", and if so, return @Just (symb, ty, val)@, where:+ --+ -- - @symb@ is the name of the global variable corresponding to the+ -- argument.+ --+ -- - @ty@ is the type of the global variable's new constant initializer.+ --+ -- - @val@ is the new constant initializer value.+ --+ -- See Note [Undoing LLVM's relative table lookup conversion pass] for an+ -- explanation of what "reltable-like" means.+ foldLoadRelConstInit :: L.Value -> Maybe (L.Symbol, L.Type, L.Value)+ foldLoadRelConstInit (L.ValSymbol s)+ | Just global <- Map.lookup s globalMap+ , Just constInit <- L.globalValue global+ -- Check that the type of the global variable is+ -- [<constInitElems> x i32].+ , L.ValArray (L.PrimType (L.Integer 32)) constInitElems <- constInit+ , Just foldedConstInitElems <-+ traverse (foldLoadRelConstInitElem global) constInitElems+ = Just ( L.globalSym global+ , L.Array (genericLength constInitElems) ptrToI8Type+ , L.ValArray ptrToI8Type foldedConstInitElems+ )+ foldLoadRelConstInit (L.ValConstExpr (L.ConstConv L.BitCast tv _)) =+ foldLoadRelConstInit (L.typedValue tv)+ foldLoadRelConstInit _ =+ Nothing++ -- Check that an element of a constant initializer is of the form+ -- `trunc(ptrtoint x - ptrtoint p)`, and if so, return `Just x`. Otherwise,+ -- return Nothing.+ foldLoadRelConstInitElem :: L.Global -> L.Value -> Maybe L.Value+ foldLoadRelConstInitElem global constInitElem+ | L.ValConstExpr+ (L.ConstConv L.Trunc+ (L.Typed { L.typedValue =+ L.ValConstExpr+ (L.ConstArith+ (L.Sub _ _)+ (L.Typed { L.typedValue =+ L.ValConstExpr (L.ConstConv L.PtrToInt x _) })+ (L.ValConstExpr (L.ConstConv L.PtrToInt p _))) })+ _truncTy) <- constInitElem+ , L.ValSymbol pSym <- L.typedValue p+ , L.globalSym global == pSym+ = Just (L.ValConstExpr (L.ConstConv L.BitCast x ptrToI8Type))++ | otherwise+ = Nothing++ -- Type type i8*.+ ptrToI8Type :: L.Type+ ptrToI8Type = L.PtrTo $ L.PrimType $ L.Integer 8++{-+Note [Undoing LLVM's relative table lookup conversion pass]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Clang 14.0.0+ include a `rel-lookup-table-converter` optimization pass that is+enabled with -O1 or greater. This optimization usually applies to code that+looks like table lookups. For instance, this pass would take this C code:++ const char *F(int tag) {+ static const char *const table[] = {+ "A",+ "B",+ };++ return table[tag];+ }++And optimize it to LLVM bitcode that looks like this:++ @reltable.F = internal unnamed_addr constant [2 x i32] [i32 trunc (i64 sub (i64 ptrtoint ([2 x i8]* @.str to i64), i64 ptrtoint ([2 x i32]* @reltable.F to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint ([2 x i8]* @.str.1 to i64), i64 ptrtoint ([2 x i32]* @reltable.F to i64)) to i32)], align 4+ @.str = private unnamed_addr constant [2 x i8] c"A\00", align 1+ @.str.1 = private unnamed_addr constant [2 x i8] c"B\00", align 1++ define dso_local i8* @F(i32 noundef %0) local_unnamed_addr #0 {+ %2 = sext i32 %0 to i64+ %3 = shl i64 %2, 2+ %4 = call i8* @llvm.load.relative.i64(i8* bitcast ([2 x i32]* @reltable.F to i8*), i64 %3)+ ret i8* %4+ }++There are several remarkable things about this LLVM bitcode:++* The definition of @F is backed up a relative lookup table @reltable.F.+ Invoking @F is tantamount to looking up a value in the table by using the+ special @llvm.load.relative.i* intrinsic, which is described here:+ https://releases.llvm.org/17.0.1/docs/LangRef.html#llvm-load-relative-intrinsic++* The definition of @reltable.F itself is quite unorthodox. Conceptually, it is+ an array of strings (@.str and @.str1), but where each element of the array+ contains the relative offset of the string to the table itself. As a result,+ it is not an array of pointers, but rather an array of i32s!++* Each i32 in the array consists of the address of each string represented as an+ integer (obtained via ptrtoint) subtracted from the address of the table,+ followed by a trunc to ensure the result fits in an i32. (One weird result of+ this encoding is that @reltable.F is defined recursively in terms of itself.)++This optimization pass is handy for Clang's purposes, as it allows Clang to+produce more efficient assembly code. Unfortunately, this encoding is quite+problematic for crucible-llvm. The problem ultimately lies in the fact that we+are performing pointer arithmetic on pointers from completely different+allocation regions (e.g., subtracting @reltable.F from @.str), which+crucible-llvm has no ability to reason about. (This optimization is also+problematic for CHERI, which tracks pointer provenance in a similar way—see+https://github.com/CTSRD-CHERI/llvm-project/issues/572).++What's more, we don't have a reliable way of avoiding this optimization, as+Clang's optimization pass manager doesn't provide a way to disable individual+passes via command-line arguments. We could tell users to downgrade from -O1+from -O0, but this would be a pretty severe workaround.++Our solution is to manually "undo" the optimization ourselves. That is, we+replace the definition of @reltable.F with bitcode that looks like this:++ @reltable.F = internal unnamed_addr constant [2 x i8*] [i8* bitcast ([2 x i8]* @.str to i8*), i8* bitcast ([2 x i8]* @.str.1 to i8*)]++This avoids any problematic uses of pointer arithmetic altogether. Here is how+we do this:++1. When processing global definitions in an LLVM module, we identify the names+ of all globals that are passed as the first argument to+ @llvm.load.relative.i*. We'll refer to these as "reltable-like" globals.++ This check assumes that the globals are passed directly to+ @llvm.load.relative.i*, rather than going through any intermediate+ variables. This is likely a safe assumption to make, considering that+ Clang's -O1 settings will usually optimize away any such intermediate+ variables.++2. For each reltable-like global, we check that the global has a constant+ initializer of type [<N> x i32] where each element is of the form+ `trunc (ptrtoint x - ptrtoint p)`. This is somewhat fragile, but the+ documentation for llvm.load.relative.i* implies that LLVM itself checks+ for code that looks like this, so we follow suit.++3. For each element in the constant initializer array, we turn+ `trunc (ptrtoint x - ptrtoint p)` into `bitcast x to i8*`. Note that the+ this changes its type from `i32` to `i8*`.++4. When translating a global definition to Crucible, we check if the global+ is reltable-like. If so, we replace its constant initializer with the+ `bitcast`ed version. We must also make sure that the global is translated+ at type `[<N> x i8*]` rather than `[<N> x i32]`.++ Furthermore, we must also make sure not to use the original global's+ alignment, as the `bitcast`ed version will almost certainly have different+ alignment requirements. We rely on crucible-llvm's alignment inference to+ figure out what the new alignment should be.++5. In the override for llvm.load.relative.i*, we make sure to adjust the second+ argument (the pointer offset). This is because LLVM assumes that the offset+ is for something of type `[<N> x i32]`, so an offset value of 4 (four bytes)+ refers to the first element, an offset value of 8 refers to the second+ element, and so on. On the other hand, something of type `[<N> x i8*]` will+ likely require different offsets, since the size of a pointer may be greater+ than four bytes (e.g., it is eight bytes on 64-bit architectures).++ To account for this difference, we divide the offset value by 4 and then+ multiply it by the number of bytes in the size of a pointer.++It is worth emphasizing that this is a very ad hoc workaround. At the same time,+it is likely the best we can do without substantially changing how crucible-llvm+tracks pointer provenance.+-}
src/Lang/Crucible/LLVM/Intrinsics.hs view
@@ -29,21 +29,17 @@ , module Lang.Crucible.LLVM.Intrinsics.Common , module Lang.Crucible.LLVM.Intrinsics.Options+, module Lang.Crucible.LLVM.Intrinsics.Match ) where import Control.Lens hiding (op, (:>), Empty)-import Control.Monad (forM_)-import Control.Monad.Reader (ReaderT(..))-import Control.Monad.Trans.Maybe-import Data.Foldable (asum)-import Data.List (stripPrefix, tails, isPrefixOf)+import Control.Monad (forM)+import Data.Maybe (catMaybes) import qualified Text.LLVM.AST as L import qualified ABI.Itanium as ABI import qualified Data.Parameterized.Map as MapF -import What4.Interface- import Lang.Crucible.Backend import Lang.Crucible.Types import Lang.Crucible.Simulator.Intrinsics@@ -59,6 +55,7 @@ import qualified Lang.Crucible.LLVM.Intrinsics.LLVM as LLVM import qualified Lang.Crucible.LLVM.Intrinsics.Libc as Libc import qualified Lang.Crucible.LLVM.Intrinsics.Libcxx as Libcxx+import Lang.Crucible.LLVM.Intrinsics.Match import Lang.Crucible.LLVM.Intrinsics.Options llvmIntrinsicTypes :: IsSymInterface sym => IntrinsicTypes sym@@ -67,18 +64,22 @@ MapF.insert (knownSymbol :: SymbolRepr "LLVM_pointer") IntrinsicMuxFn $ MapF.empty --- | Register all declare and define overrides+-- | Match two sets of 'OverrideTemplate's against the @declare@s and @define@s+-- in a 'L.Module', registering all the overrides that apply and returning them+-- as a list. register_llvm_overrides :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch , ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions ) => L.Module ->- [OverrideTemplate p sym arch rtp l a] {- ^ Additional "define" overrides -} ->- [OverrideTemplate p sym arch rtp l a] {- ^ Additional "declare" overrides -} ->+ [OverrideTemplate p sym LLVM arch] {- ^ Additional \"define\" overrides -} ->+ [OverrideTemplate p sym LLVM arch] {- ^ Additional \"declare\" overrides -} -> LLVMContext arch ->- OverrideSim p sym LLVM rtp l a ()+ -- | Applied (@define@ overrides, @declare@ overrides)+ OverrideSim p sym LLVM rtp l a ([SomeLLVMOverride p sym LLVM], [SomeLLVMOverride p sym LLVM]) register_llvm_overrides llvmModule defineOvrs declareOvrs llvmctx =- do register_llvm_define_overrides llvmModule defineOvrs llvmctx- register_llvm_declare_overrides llvmModule declareOvrs llvmctx+ do defOvs <- register_llvm_define_overrides llvmModule defineOvrs llvmctx+ declOvs <- register_llvm_declare_overrides llvmModule declareOvrs llvmctx+ pure (defOvs, declOvs) -- | Filter the initial list of templates to only those that could -- possibly match the given declaration based on straightforward,@@ -88,307 +89,100 @@ -- more detail, including examining function arguments -- and the structure of C++ demangled names to extract more information. filterTemplates ::- [OverrideTemplate p sym arch rtp l a] ->+ [OverrideTemplate p sym ext arch] -> L.Declare ->- [OverrideTemplate p sym arch rtp l a]-filterTemplates ts decl = filter (f . overrideTemplateMatcher) ts- where- L.Symbol nm = L.decName decl-- f (ExactMatch x) = x == nm- f (PrefixMatch pfx) = pfx `isPrefixOf` nm- f (SubstringsMatch as) = filterSubstrings as nm-- filterSubstrings [] _ = True- filterSubstrings (a:as) xs =- case restAfterSubstring a xs of- Nothing -> False- Just rest -> filterSubstrings as rest-- restAfterSubstring :: String -> String -> Maybe String- restAfterSubstring sub xs = asum [ stripPrefix sub tl | tl <- tails xs ]+ [OverrideTemplate p sym ext arch]+filterTemplates ts decl = filter (matches nm . overrideTemplateMatcher) ts+ where L.Symbol nm = L.decName decl +-- | Match a set of 'OverrideTemplate's against a single 'L.Declare',+-- registering all the overrides that apply and returning them as a list.+match_llvm_overrides ::+ (IsSymInterface sym, HasLLVMAnn sym) =>+ LLVMContext arch ->+ -- | Overrides to attempt to match against this declaration+ [OverrideTemplate p sym ext arch] ->+ -- | Declaration of the function that might get overridden+ L.Declare ->+ OverrideSim p sym ext rtp l a [SomeLLVMOverride p sym ext]+match_llvm_overrides llvmctx acts decl =+ llvmPtrWidth llvmctx $ \wptr -> withPtrWidth wptr $ do+ let acts' = filterTemplates acts decl+ let L.Symbol nm = L.decName decl+ let declnm = either (const Nothing) Just $ ABI.demangleName nm+ mbOvs <-+ forM (map overrideTemplateAction acts') $ \(MakeOverride act) ->+ case act decl declnm llvmctx of+ Nothing -> pure Nothing+ Just sov@(SomeLLVMOverride ov) -> do+ register_llvm_override ov decl llvmctx+ pure (Just sov)+ pure (catMaybes mbOvs) --- | Helper function for registering overrides+-- | Match a set of 'OverrideTemplate's against a set of 'L.Declare's,+-- registering all the overrides that apply and returning them as a list. register_llvm_overrides_ ::+ (IsSymInterface sym, HasLLVMAnn sym) => LLVMContext arch ->- [OverrideTemplate p sym arch rtp l a] ->+ -- | Overrides to attempt to match against these declarations+ [OverrideTemplate p sym ext arch] ->+ -- | Declarations of the functions that might get overridden [L.Declare] ->- OverrideSim p sym LLVM rtp l a ()+ OverrideSim p sym ext rtp l a [SomeLLVMOverride p sym ext] register_llvm_overrides_ llvmctx acts decls =- forM_ decls $ \decl ->- do let acts' = filterTemplates acts decl- let L.Symbol nm = L.decName decl- let declnm = either (const Nothing) Just $ ABI.demangleName nm- runMaybeT (flip runReaderT (decl,declnm,llvmctx) $ asum (map overrideTemplateAction acts'))+ concat <$> forM decls (\decl -> match_llvm_overrides llvmctx acts decl) +-- | Match a set of 'OverrideTemplate's against all the @declare@s and @define@s+-- in a 'L.Module', registering all the overrides that apply and returning them+-- as a list.+--+-- Registers a default set of overrides, in addition to the ones passed as an+-- argument. register_llvm_define_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => L.Module ->- [OverrideTemplate p sym arch rtp l a] ->+ -- | Additional (non-default) @define@ overrides+ [OverrideTemplate p sym LLVM arch] -> LLVMContext arch ->- OverrideSim p sym LLVM rtp l a ()+ OverrideSim p sym LLVM rtp l a [SomeLLVMOverride p sym LLVM] register_llvm_define_overrides llvmModule addlOvrs llvmctx = let ?lc = llvmctx^.llvmTypeCtx in register_llvm_overrides_ llvmctx (addlOvrs ++ define_overrides) $ (allModuleDeclares llvmModule) +-- | Match a set of 'OverrideTemplate's against all the @declare@s in a+-- 'L.Module', registering all the overrides that apply and returning them as+-- a list.+--+-- Registers a default set of overrides, in addition to the ones passed as an+-- argument. register_llvm_declare_overrides :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch , ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions ) => L.Module ->- [OverrideTemplate p sym arch rtp l a] ->+ -- | Additional (non-default) @declare@ overrides+ [OverrideTemplate p sym LLVM arch] -> LLVMContext arch ->- OverrideSim p sym LLVM rtp l a ()+ OverrideSim p sym LLVM rtp l a [SomeLLVMOverride p sym LLVM] register_llvm_declare_overrides llvmModule addlOvrs llvmctx = let ?lc = llvmctx^.llvmTypeCtx in register_llvm_overrides_ llvmctx (addlOvrs ++ declare_overrides) $ L.modDeclares llvmModule - -- | Register overrides for declared-but-not-defined functions declare_overrides :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch , ?lc :: TypeContext, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions ) =>- [OverrideTemplate p sym arch rtp l a]+ [OverrideTemplate p sym LLVM arch] declare_overrides =- [ basic_llvm_override LLVM.llvmLifetimeStartOverride- , basic_llvm_override LLVM.llvmLifetimeEndOverride- , basic_llvm_override (LLVM.llvmLifetimeOverrideOverload "start" (knownNat @8))- , basic_llvm_override (LLVM.llvmLifetimeOverrideOverload "end" (knownNat @8))- , basic_llvm_override (LLVM.llvmLifetimeOverrideOverload_opaque "start")- , basic_llvm_override (LLVM.llvmLifetimeOverrideOverload_opaque "end")- , basic_llvm_override (LLVM.llvmInvariantStartOverride (knownNat @8))- , basic_llvm_override LLVM.llvmInvariantStartOverride_opaque- , basic_llvm_override (LLVM.llvmInvariantEndOverride (knownNat @8))- , basic_llvm_override LLVM.llvmInvariantEndOverride_opaque-- , basic_llvm_override LLVM.llvmAssumeOverride- , basic_llvm_override LLVM.llvmTrapOverride- , basic_llvm_override LLVM.llvmUBSanTrapOverride-- , basic_llvm_override LLVM.llvmMemcpyOverride_8_8_32- , basic_llvm_override LLVM.llvmMemcpyOverride_8_8_32_noalign- , basic_llvm_override LLVM.llvmMemcpyOverride_8_8_32_noalign_opaque- , basic_llvm_override LLVM.llvmMemcpyOverride_8_8_64- , basic_llvm_override LLVM.llvmMemcpyOverride_8_8_64_noalign- , basic_llvm_override LLVM.llvmMemcpyOverride_8_8_64_noalign_opaque-- , basic_llvm_override LLVM.llvmMemmoveOverride_8_8_32- , basic_llvm_override LLVM.llvmMemmoveOverride_8_8_32_noalign- , basic_llvm_override LLVM.llvmMemmoveOverride_8_8_32_noalign_opaque- , basic_llvm_override LLVM.llvmMemmoveOverride_8_8_64- , basic_llvm_override LLVM.llvmMemmoveOverride_8_8_64_noalign- , basic_llvm_override LLVM.llvmMemmoveOverride_8_8_64_noalign_opaque-- , basic_llvm_override LLVM.llvmMemsetOverride_8_32- , basic_llvm_override LLVM.llvmMemsetOverride_8_32_noalign- , basic_llvm_override LLVM.llvmMemsetOverride_8_32_noalign_opaque- , basic_llvm_override LLVM.llvmMemsetOverride_8_64- , basic_llvm_override LLVM.llvmMemsetOverride_8_64_noalign- , basic_llvm_override LLVM.llvmMemsetOverride_8_64_noalign_opaque-- , basic_llvm_override LLVM.llvmObjectsizeOverride_32- , basic_llvm_override LLVM.llvmObjectsizeOverride_64-- , basic_llvm_override LLVM.llvmObjectsizeOverride_32_null- , basic_llvm_override LLVM.llvmObjectsizeOverride_64_null-- , basic_llvm_override LLVM.llvmObjectsizeOverride_32_null_dynamic- , basic_llvm_override LLVM.llvmObjectsizeOverride_64_null_dynamic-- , basic_llvm_override LLVM.llvmObjectsizeOverride_32_null_dynamic_opaque- , basic_llvm_override LLVM.llvmObjectsizeOverride_64_null_dynamic_opaque-- , basic_llvm_override LLVM.llvmPrefetchOverride- , basic_llvm_override LLVM.llvmPrefetchOverride_opaque- , basic_llvm_override LLVM.llvmPrefetchOverride_preLLVM10-- , basic_llvm_override LLVM.llvmStacksave- , basic_llvm_override LLVM.llvmStackrestore-- , polymorphic1_llvm_override "llvm.ctlz"- (\w -> SomeLLVMOverride (LLVM.llvmCtlz w))- , polymorphic1_llvm_override "llvm.cttz"- (\w -> SomeLLVMOverride (LLVM.llvmCttz w))- , polymorphic1_llvm_override "llvm.ctpop"- (\w -> SomeLLVMOverride (LLVM.llvmCtpop w))- , polymorphic1_llvm_override "llvm.bitreverse"- (\w -> SomeLLVMOverride (LLVM.llvmBitreverse w))- , polymorphic1_llvm_override "llvm.abs"- (\w -> SomeLLVMOverride (LLVM.llvmAbsOverride w))-- , basic_llvm_override (LLVM.llvmBSwapOverride (knownNat @2)) -- 16 = 2 * 8- , basic_llvm_override (LLVM.llvmBSwapOverride (knownNat @4)) -- 32 = 4 * 8- , basic_llvm_override (LLVM.llvmBSwapOverride (knownNat @6)) -- 48 = 6 * 8- , basic_llvm_override (LLVM.llvmBSwapOverride (knownNat @8)) -- 64 = 8 * 8- , basic_llvm_override (LLVM.llvmBSwapOverride (knownNat @10)) -- 80 = 10 * 8- , basic_llvm_override (LLVM.llvmBSwapOverride (knownNat @12)) -- 96 = 12 * 8- , basic_llvm_override (LLVM.llvmBSwapOverride (knownNat @14)) -- 112 = 14 * 8- , basic_llvm_override (LLVM.llvmBSwapOverride (knownNat @16)) -- 128 = 16 * 8-- , polymorphic1_llvm_override "llvm.fshl"- (\w -> SomeLLVMOverride (LLVM.llvmFshl w))- , polymorphic1_llvm_override "llvm.fshr"- (\w -> SomeLLVMOverride (LLVM.llvmFshr w))-- , polymorphic1_llvm_override "llvm.expect"- (\w -> SomeLLVMOverride (LLVM.llvmExpectOverride w))- , polymorphic1_llvm_override "llvm.sadd.with.overflow"- (\w -> SomeLLVMOverride (LLVM.llvmSaddWithOverflow w))- , polymorphic1_llvm_override "llvm.uadd.with.overflow"- (\w -> SomeLLVMOverride (LLVM.llvmUaddWithOverflow w))- , polymorphic1_llvm_override "llvm.ssub.with.overflow"- (\w -> SomeLLVMOverride (LLVM.llvmSsubWithOverflow w))- , polymorphic1_llvm_override "llvm.usub.with.overflow"- (\w -> SomeLLVMOverride (LLVM.llvmUsubWithOverflow w))- , polymorphic1_llvm_override "llvm.smul.with.overflow"- (\w -> SomeLLVMOverride (LLVM.llvmSmulWithOverflow w))- , polymorphic1_llvm_override "llvm.umul.with.overflow"- (\w -> SomeLLVMOverride (LLVM.llvmUmulWithOverflow w))-- , polymorphic1_llvm_override "llvm.smax"- (\w -> SomeLLVMOverride (LLVM.llvmSmax w))- , polymorphic1_llvm_override "llvm.smin"- (\w -> SomeLLVMOverride (LLVM.llvmSmin w))- , polymorphic1_llvm_override "llvm.umax"- (\w -> SomeLLVMOverride (LLVM.llvmUmax w))- , polymorphic1_llvm_override "llvm.umin"- (\w -> SomeLLVMOverride (LLVM.llvmUmin w))-- , basic_llvm_override LLVM.llvmCopysignOverride_F32- , basic_llvm_override LLVM.llvmCopysignOverride_F64- , basic_llvm_override LLVM.llvmFabsF32- , basic_llvm_override LLVM.llvmFabsF64-- , basic_llvm_override LLVM.llvmCeilOverride_F32- , basic_llvm_override LLVM.llvmCeilOverride_F64- , basic_llvm_override LLVM.llvmFloorOverride_F32- , basic_llvm_override LLVM.llvmFloorOverride_F64- , basic_llvm_override LLVM.llvmSqrtOverride_F32- , basic_llvm_override LLVM.llvmSqrtOverride_F64- , basic_llvm_override LLVM.llvmSinOverride_F32- , basic_llvm_override LLVM.llvmSinOverride_F64- , basic_llvm_override LLVM.llvmCosOverride_F32- , basic_llvm_override LLVM.llvmCosOverride_F64- , basic_llvm_override LLVM.llvmPowOverride_F32- , basic_llvm_override LLVM.llvmPowOverride_F64- , basic_llvm_override LLVM.llvmExpOverride_F32- , basic_llvm_override LLVM.llvmExpOverride_F64- , basic_llvm_override LLVM.llvmLogOverride_F32- , basic_llvm_override LLVM.llvmLogOverride_F64- , basic_llvm_override LLVM.llvmExp2Override_F32- , basic_llvm_override LLVM.llvmExp2Override_F64- , basic_llvm_override LLVM.llvmLog2Override_F32- , basic_llvm_override LLVM.llvmLog2Override_F64- , basic_llvm_override LLVM.llvmLog10Override_F32- , basic_llvm_override LLVM.llvmLog10Override_F64- , basic_llvm_override LLVM.llvmFmaOverride_F32- , basic_llvm_override LLVM.llvmFmaOverride_F64- , basic_llvm_override LLVM.llvmFmuladdOverride_F32- , basic_llvm_override LLVM.llvmFmuladdOverride_F64- , basic_llvm_override LLVM.llvmIsFpclassOverride_F32- , basic_llvm_override LLVM.llvmIsFpclassOverride_F64-- -- C standard library functions- , basic_llvm_override Libc.llvmAbortOverride- , basic_llvm_override Libc.llvmAssertRtnOverride- , basic_llvm_override Libc.llvmAssertFailOverride- , basic_llvm_override Libc.llvmMemcpyOverride- , basic_llvm_override Libc.llvmMemcpyChkOverride- , basic_llvm_override Libc.llvmMemmoveOverride- , basic_llvm_override Libc.llvmMemsetOverride- , basic_llvm_override Libc.llvmMemsetChkOverride- , basic_llvm_override Libc.llvmMallocOverride- , basic_llvm_override Libc.llvmCallocOverride- , basic_llvm_override Libc.llvmFreeOverride- , basic_llvm_override Libc.llvmReallocOverride- , basic_llvm_override Libc.llvmStrlenOverride- , basic_llvm_override Libc.llvmPrintfOverride- , basic_llvm_override Libc.llvmPrintfChkOverride- , basic_llvm_override Libc.llvmPutsOverride- , basic_llvm_override Libc.llvmPutCharOverride- , basic_llvm_override Libc.llvmExitOverride- , basic_llvm_override Libc.llvmGetenvOverride- , basic_llvm_override Libc.llvmHtonlOverride- , basic_llvm_override Libc.llvmHtonsOverride- , basic_llvm_override Libc.llvmNtohlOverride- , basic_llvm_override Libc.llvmNtohsOverride- , basic_llvm_override Libc.llvmAbsOverride- , basic_llvm_override Libc.llvmLAbsOverride_32- , basic_llvm_override Libc.llvmLAbsOverride_64- , basic_llvm_override Libc.llvmLLAbsOverride-- , basic_llvm_override Libc.llvmCeilOverride- , basic_llvm_override Libc.llvmCeilfOverride- , basic_llvm_override Libc.llvmFloorOverride- , basic_llvm_override Libc.llvmFloorfOverride- , basic_llvm_override Libc.llvmFmaOverride- , basic_llvm_override Libc.llvmFmafOverride- , basic_llvm_override Libc.llvmIsinfOverride- , basic_llvm_override Libc.llvm__isinfOverride- , basic_llvm_override Libc.llvm__isinffOverride- , basic_llvm_override Libc.llvmIsnanOverride- , basic_llvm_override Libc.llvm__isnanOverride- , basic_llvm_override Libc.llvm__isnanfOverride- , basic_llvm_override Libc.llvmSqrtOverride- , basic_llvm_override Libc.llvmSqrtfOverride- , basic_llvm_override Libc.llvmSinOverride- , basic_llvm_override Libc.llvmSinfOverride- , basic_llvm_override Libc.llvmCosOverride- , basic_llvm_override Libc.llvmCosfOverride- , basic_llvm_override Libc.llvmTanOverride- , basic_llvm_override Libc.llvmTanfOverride- , basic_llvm_override Libc.llvmAsinOverride- , basic_llvm_override Libc.llvmAsinfOverride- , basic_llvm_override Libc.llvmAcosOverride- , basic_llvm_override Libc.llvmAcosfOverride- , basic_llvm_override Libc.llvmAtanOverride- , basic_llvm_override Libc.llvmAtanfOverride- , basic_llvm_override Libc.llvmSinhOverride- , basic_llvm_override Libc.llvmSinhfOverride- , basic_llvm_override Libc.llvmCoshOverride- , basic_llvm_override Libc.llvmCoshfOverride- , basic_llvm_override Libc.llvmTanhOverride- , basic_llvm_override Libc.llvmTanhfOverride- , basic_llvm_override Libc.llvmAsinhOverride- , basic_llvm_override Libc.llvmAsinhfOverride- , basic_llvm_override Libc.llvmAcoshOverride- , basic_llvm_override Libc.llvmAcoshfOverride- , basic_llvm_override Libc.llvmAtanhOverride- , basic_llvm_override Libc.llvmAtanhfOverride- , basic_llvm_override Libc.llvmHypotOverride- , basic_llvm_override Libc.llvmHypotfOverride- , basic_llvm_override Libc.llvmAtan2Override- , basic_llvm_override Libc.llvmAtan2fOverride- , basic_llvm_override Libc.llvmPowfOverride- , basic_llvm_override Libc.llvmPowOverride- , basic_llvm_override Libc.llvmExpOverride- , basic_llvm_override Libc.llvmExpfOverride- , basic_llvm_override Libc.llvmLogOverride- , basic_llvm_override Libc.llvmLogfOverride- , basic_llvm_override Libc.llvmExpm1Override- , basic_llvm_override Libc.llvmExpm1fOverride- , basic_llvm_override Libc.llvmLog1pOverride- , basic_llvm_override Libc.llvmLog1pfOverride- , basic_llvm_override Libc.llvmExp2Override- , basic_llvm_override Libc.llvmExp2fOverride- , basic_llvm_override Libc.llvmLog2Override- , basic_llvm_override Libc.llvmLog2fOverride- , basic_llvm_override Libc.llvmExp10Override- , basic_llvm_override Libc.llvmExp10fOverride- , basic_llvm_override Libc.llvmLog10Override- , basic_llvm_override Libc.llvmLog10fOverride-- , basic_llvm_override Libc.cxa_atexitOverride- , basic_llvm_override Libc.posixMemalignOverride+ concat+ [ map (\(SomeLLVMOverride ov) -> basic_llvm_override ov) Libc.libc_overrides+ , map (\(SomeLLVMOverride ov) -> basic_llvm_override ov) LLVM.basic_llvm_overrides+ , map (\(pfx, LLVM.Poly1LLVMOverride ov) -> polymorphic1_llvm_override pfx ov) LLVM.poly1_llvm_overrides+ , map (\(pfx, LLVM.Poly1VecLLVMOverride ov) -> polymorphic1_vec_llvm_override pfx ov) LLVM.poly1_vec_llvm_overrides -- C++ standard library functions- , Libcxx.register_cpp_override Libcxx.endlOverride-- -- Some architecture-dependent intrinsics- , basic_llvm_override LLVM.llvmX86_SSE2_storeu_dq- , basic_llvm_override LLVM.llvmX86_pclmulqdq+ , [ Libcxx.register_cpp_override Libcxx.endlOverride ] ] @@ -396,7 +190,7 @@ -- function has a definition define_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch, ?lc :: TypeContext) =>- [OverrideTemplate p sym arch rtp l a]+ [OverrideTemplate p sym LLVM arch] define_overrides = [ Libcxx.register_cpp_override Libcxx.putToOverride12 , Libcxx.register_cpp_override Libcxx.putToOverride9
+ src/Lang/Crucible/LLVM/Intrinsics/Cast.hs view
@@ -0,0 +1,133 @@+-- |+-- Module : Lang.Crucible.LLVM.Intrinsics.Cast+-- Description : Cast between bitvectors and pointers in signatures+-- Copyright : (c) Galois, Inc 2024+-- License : BSD3+-- Maintainer : Langston Barrett <langston@galois.com>+-- Stability : provisional+--+-- The built-in overrides in "Lang.Crucible.LLVM.Intrinsics.Libc" and+-- "Lang.Crucible.LLVM.Intrinsics.LLVM" frequently take arguments of type+-- 'Lang.Crucible.Types.BVType', but at runtime everything is represented as an+-- 'Lang.Crucible.LLVM.MemModel.Pointer.LLVMPtr'. This module contains helpers+-- for \"casting\" between pointers and bitvectors.+------------------------------------------------------------------------++{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Lang.Crucible.LLVM.Intrinsics.Cast+ ( ValCastError+ , printValCastError+ , ArgCast(applyArgCast)+ , ValCast(applyValCast)+ , castLLVMArgs+ , castLLVMRet+ ) where++import Control.Monad.IO.Class (liftIO)+import Control.Lens+import qualified Data.Text as Text++import qualified Data.Parameterized.Context as Ctx+import Data.Parameterized.Some (Some(Some))+import Data.Parameterized.TraversableFC (fmapFC)++import What4.FunctionName (FunctionName (functionName))++import Lang.Crucible.Backend+import Lang.Crucible.Simulator (SimErrorReason(AssertFailureSimError))+import Lang.Crucible.Simulator.OverrideSim+import Lang.Crucible.Simulator.RegMap+import Lang.Crucible.Types++import Lang.Crucible.LLVM.MemModel.Partial (ptrToBv)+import Lang.Crucible.LLVM.MemModel.Pointer++data ValCastError+ = -- | Mismatched number of arguments ('castLLVMArgs') or struct fields+ -- ('castLLVMRet').+ MismatchedShape+ -- | Can\'t cast between these types+ | ValCastError (Some TypeRepr) (Some TypeRepr)++-- | Turn a 'ValCastError' into a human-readable message (lines).+printValCastError :: ValCastError -> [String]+printValCastError =+ \case+ MismatchedShape -> ["argument shape mismatch"]+ ValCastError (Some ret) (Some ret') ->+ [ "Cannot cast types"+ , "*** Source type: " ++ show ret+ , "*** Target type: " ++ show ret'+ ]++-- | A function to (infallibly) cast between 'Ctx.Assignment's of 'RegEntry's.+newtype ArgCast p sym ext args args' =+ ArgCast { applyArgCast :: (forall rtp l a.+ Ctx.Assignment (RegEntry sym) args ->+ OverrideSim p sym ext rtp l a (Ctx.Assignment (RegEntry sym) args')) }++-- | A function to (infallibly) cast a value of types @tp@ to @tp'@.+newtype ValCast p sym ext tp tp' =+ ValCast { applyValCast :: (forall rtp l a.+ RegValue sym tp ->+ OverrideSim p sym ext rtp l a (RegValue sym tp')) }++-- | Attempt to construct a function to cast between 'Ctx.Assignment's of+-- 'RegEntry's.+castLLVMArgs :: forall p sym ext bak args args'.+ IsSymBackend sym bak =>+ -- | Only used in error messages+ FunctionName ->+ bak ->+ CtxRepr args' ->+ CtxRepr args ->+ Either ValCastError (ArgCast p sym ext args args')+castLLVMArgs _fnm _ Ctx.Empty Ctx.Empty =+ Right (ArgCast (\_ -> return Ctx.Empty))+castLLVMArgs fnm bak (rest' Ctx.:> tp') (rest Ctx.:> tp) =+ do ValCast f <- castLLVMRet fnm bak tp tp'+ ArgCast fs <- castLLVMArgs fnm bak rest' rest+ Right (ArgCast+ (\(xs Ctx.:> x) -> do+ xs' <- fs xs+ x' <- f (regValue x)+ pure (xs' Ctx.:> RegEntry tp' x')))+castLLVMArgs _ _ _ _ = Left MismatchedShape++-- | Attempt to construct a function to cast values of type @ret@ to type+-- @ret'@.+castLLVMRet ::+ IsSymBackend sym bak =>+ -- | Only used in error messages+ FunctionName ->+ bak ->+ TypeRepr ret ->+ TypeRepr ret' ->+ Either ValCastError (ValCast p sym ext ret ret')+castLLVMRet _fnm bak (BVRepr w) (LLVMPointerRepr w')+ | Just Refl <- testEquality w w'+ = Right (ValCast (liftIO . llvmPointer_bv (backendGetSym bak)))+castLLVMRet fnm bak (LLVMPointerRepr w) (BVRepr w')+ | Just Refl <- testEquality w w'+ = let err = + AssertFailureSimError+ "Found a pointer where a bitvector was expected"+ ("In the arguments or return value of" ++ Text.unpack (functionName fnm)) in+ Right (ValCast (liftIO . ptrToBv bak err))+castLLVMRet fnm bak (VectorRepr tp) (VectorRepr tp')+ = do ValCast f <- castLLVMRet fnm bak tp tp'+ Right (ValCast (traverse f))+castLLVMRet fnm bak (StructRepr ctx) (StructRepr ctx')+ = do ArgCast tf <- castLLVMArgs fnm bak ctx' ctx+ Right (ValCast (\vals ->+ let vals' = Ctx.zipWith (\tp (RV v) -> RegEntry tp v) ctx vals in+ fmapFC (\x -> RV (regValue x)) <$> tf vals'))++castLLVMRet _fnm _bak ret ret'+ | Just Refl <- testEquality ret ret'+ = Right (ValCast return)+castLLVMRet _fnm _bak ret ret' = Left (ValCastError (Some ret) (Some ret'))
src/Lang/Crucible/LLVM/Intrinsics/Common.hs view
@@ -20,48 +20,42 @@ module Lang.Crucible.LLVM.Intrinsics.Common ( LLVMOverride(..) , SomeLLVMOverride(..)- , RegOverrideM+ , MakeOverride(..) , llvmSizeT , llvmSSizeT , OverrideTemplate(..)- , TemplateMatcher(..) , callStackFromMemVar' -- ** register_llvm_override , basic_llvm_override , polymorphic1_llvm_override+ , polymorphic1_vec_llvm_override , build_llvm_override , register_llvm_override , register_1arg_polymorphic_override- , bind_llvm_handle- , bind_llvm_func+ , register_1arg_vec_polymorphic_override , do_register_llvm_override , alloc_and_register_override ) where import qualified Text.LLVM.AST as L -import Control.Applicative (empty) import Control.Monad (when) import Control.Monad.IO.Class (liftIO) import Control.Lens-import Control.Monad.Reader (ReaderT, ask, lift)-import Control.Monad.Trans.Maybe (MaybeT) import qualified Data.List as List import qualified Data.Text as Text import Numeric (readDec)+import qualified System.Info as Info import qualified ABI.Itanium as ABI import qualified Data.Parameterized.Context as Ctx import Data.Parameterized.Some (Some(..))-import Data.Parameterized.TraversableFC (fmapFC) import Lang.Crucible.Backend import Lang.Crucible.CFG.Common (GlobalVar) import Lang.Crucible.Simulator.ExecutionTree (FnState(UseOverride))-import Lang.Crucible.FunctionHandle (FnHandle, mkHandle') import Lang.Crucible.Panic (panic)-import Lang.Crucible.Simulator (stateContext, simHandleAllocator) import Lang.Crucible.Simulator.OverrideSim import Lang.Crucible.Utils.MonadVerbosity (getLogFunction) import Lang.Crucible.Simulator.RegMap@@ -71,33 +65,37 @@ import Lang.Crucible.LLVM.Extension import Lang.Crucible.LLVM.Eval (callStackFromMemVar)-import Lang.Crucible.LLVM.Globals (registerFunPtr)+import Lang.Crucible.LLVM.Functions (registerFunPtr, bindLLVMFunc) import Lang.Crucible.LLVM.MemModel import Lang.Crucible.LLVM.MemModel.CallStack (CallStack)+import qualified Lang.Crucible.LLVM.Intrinsics.Cast as Cast+import qualified Lang.Crucible.LLVM.Intrinsics.Match as Match import Lang.Crucible.LLVM.Translation.Monad import Lang.Crucible.LLVM.Translation.Types -- | This type represents an implementation of an LLVM intrinsic function in -- Crucible.-data LLVMOverride p sym args ret =+--+-- This is parameterized over @ext@ so that 'LLVMOverride's can more easily be+-- reused in the context of other language extensions that are also based on the+-- LLVM memory model, such as Macaw.+data LLVMOverride p sym ext args ret = LLVMOverride { llvmOverride_declare :: L.Declare -- ^ An LLVM name and signature for this intrinsic , llvmOverride_args :: CtxRepr args -- ^ A representation of the argument types , llvmOverride_ret :: TypeRepr ret -- ^ A representation of the return type , llvmOverride_def ::- forall bak.- IsSymBackend sym bak =>- GlobalVar Mem ->- bak ->- Ctx.Assignment (RegEntry sym) args ->- forall rtp args' ret'.- OverrideSim p sym LLVM rtp args' ret' (RegValue sym ret)+ IsSymInterface sym =>+ GlobalVar Mem ->+ Ctx.Assignment (RegEntry sym) args ->+ forall rtp args' ret'.+ OverrideSim p sym ext rtp args' ret' (RegValue sym ret) -- ^ The implementation of the intrinsic in the simulator monad -- (@OverrideSim@). } -data SomeLLVMOverride p sym =- forall args ret. SomeLLVMOverride (LLVMOverride p sym args ret)+data SomeLLVMOverride p sym ext =+ forall args ret. SomeLLVMOverride (LLVMOverride p sym ext args ret) -- | Convenient LLVM representation of the @size_t@ type. llvmSizeT :: HasPtrWidth wptr => L.Type@@ -107,23 +105,31 @@ llvmSSizeT :: HasPtrWidth wptr => L.Type llvmSSizeT = L.PrimType $ L.Integer $ fromIntegral $ natValue $ PtrWidth -data OverrideTemplate p sym arch rtp l a =+-- | A funcion that inspects an LLVM declaration (along with some other data),+-- and constructs an override for the declaration if it can.+newtype MakeOverride p sym ext arch =+ MakeOverride+ { runMakeOverride ::+ L.Declare ->+ -- Decoded version of the name in the declaration+ Maybe ABI.DecodedName ->+ LLVMContext arch ->+ Maybe (SomeLLVMOverride p sym ext)+ }++-- | Checking if an override applies to a given declaration happens in two+-- \"phases\", corresponding to the fields of this struct.+data OverrideTemplate p sym ext arch = OverrideTemplate- { overrideTemplateMatcher :: TemplateMatcher- , overrideTemplateAction :: RegOverrideM p sym arch rtp l a ()+ { -- | An initial, quick, string-based check if an override might apply to a+ -- given declaration, based on its name+ overrideTemplateMatcher :: Match.TemplateMatcher+ -- | If the 'Match.TemplateMatcher' does indeed match, this slower+ -- 'MakeOverride' performs additional checks and potentially constructs+ -- a 'SomeLLVMOverride'.+ , overrideTemplateAction :: MakeOverride p sym ext arch } --- | This type controls whether an override is installed for a given name found in a module.--- See 'filterTemplates'.-data TemplateMatcher- = ExactMatch String- | PrefixMatch String- | SubstringsMatch [String]--type RegOverrideM p sym arch rtp l a =- ReaderT (L.Declare, Maybe ABI.DecodedName, LLVMContext arch)- (MaybeT (OverrideSim p sym LLVM rtp l a))- callStackFromMemVar' :: GlobalVar Mem -> OverrideSim p sym ext r args ret CallStack@@ -132,74 +138,6 @@ ------------------------------------------------------------------------ -- ** register_llvm_override -newtype ArgTransformer p sym args args' =- ArgTransformer { applyArgTransformer :: (forall rtp l a.- Ctx.Assignment (RegEntry sym) args ->- OverrideSim p sym LLVM rtp l a (Ctx.Assignment (RegEntry sym) args')) }--newtype ValTransformer p sym tp tp' =- ValTransformer { applyValTransformer :: (forall rtp l a.- RegValue sym tp ->- OverrideSim p sym LLVM rtp l a (RegValue sym tp')) }--transformLLVMArgs :: forall m p sym bak args args'.- (IsSymBackend sym bak, Monad m, HasLLVMAnn sym) =>- -- | This function name is only used in panic messages.- FunctionName ->- bak ->- CtxRepr args' ->- CtxRepr args ->- m (ArgTransformer p sym args args')-transformLLVMArgs _fnName _ Ctx.Empty Ctx.Empty =- return (ArgTransformer (\_ -> return Ctx.Empty))-transformLLVMArgs fnName bak (rest' Ctx.:> tp') (rest Ctx.:> tp) = do- return (ArgTransformer- (\(xs Ctx.:> x) ->- do (ValTransformer f) <- transformLLVMRet fnName bak tp tp'- (ArgTransformer fs) <- transformLLVMArgs fnName bak rest' rest- xs' <- fs xs- x' <- RegEntry tp' <$> f (regValue x)- pure (xs' Ctx.:> x')))-transformLLVMArgs fnName _ _ _ =- panic "Intrinsics.transformLLVMArgs"- [ "transformLLVMArgs: argument shape mismatch!"- , "in function: " ++ Text.unpack (functionName fnName)- ]--transformLLVMRet ::- (IsSymBackend sym bak, Monad m, HasLLVMAnn sym) =>- -- | This function name is only used in panic messages.- FunctionName ->- bak ->- TypeRepr ret ->- TypeRepr ret' ->- m (ValTransformer p sym ret ret')-transformLLVMRet _fnName bak (BVRepr w) (LLVMPointerRepr w')- | Just Refl <- testEquality w w'- = return (ValTransformer (liftIO . llvmPointer_bv (backendGetSym bak)))-transformLLVMRet _fnName bak (LLVMPointerRepr w) (BVRepr w')- | Just Refl <- testEquality w w'- = return (ValTransformer (liftIO . projectLLVM_bv bak))-transformLLVMRet fnName bak (VectorRepr tp) (VectorRepr tp')- = do ValTransformer f <- transformLLVMRet fnName bak tp tp'- return (ValTransformer (traverse f))-transformLLVMRet fnName bak (StructRepr ctx) (StructRepr ctx')- = do ArgTransformer tf <- transformLLVMArgs fnName bak ctx' ctx- return (ValTransformer (\vals ->- let vals' = Ctx.zipWith (\tp (RV v) -> RegEntry tp v) ctx vals in- fmapFC (\x -> RV (regValue x)) <$> tf vals'))--transformLLVMRet _fnName _bak ret ret'- | Just Refl <- testEquality ret ret'- = return (ValTransformer return)-transformLLVMRet fnName _bak ret ret'- = panic "Intrinsics.transformLLVMRet"- [ "Cannot transform types"- , "*** Source type: " ++ show ret- , "*** Target type: " ++ show ret'- , "in function: " ++ Text.unpack (functionName fnName)- ]- -- | Do some pipe-fitting to match a Crucible override function into the shape -- expected by the LLVM calling convention. This basically just coerces -- between values of @BVType w@ and values of @LLVMPointerType w@.@@ -210,50 +148,142 @@ TypeRepr ret -> CtxRepr args' -> TypeRepr ret' ->- (forall bak rtp' l' a'. IsSymBackend sym bak =>- bak ->+ (forall rtp' l' a'. IsSymInterface sym => Ctx.Assignment (RegEntry sym) args ->- OverrideSim p sym LLVM rtp' l' a' (RegValue sym ret)) ->- OverrideSim p sym LLVM rtp l a (Override p sym LLVM args' ret')+ OverrideSim p sym ext rtp' l' a' (RegValue sym ret)) ->+ OverrideSim p sym ext rtp l a (Override p sym ext args' ret') build_llvm_override fnm args ret args' ret' llvmOverride = ovrWithBackend $ \bak ->- do fargs <- transformLLVMArgs fnm bak args args'- fret <- transformLLVMRet fnm bak ret ret'+ do fargs <-+ case Cast.castLLVMArgs fnm bak args args' of+ Left err ->+ panic "Intrinsics.build_llvm_override"+ (Cast.printValCastError err +++ [ "in function: " ++ Text.unpack (functionName fnm) ])+ Right f -> pure f+ fret <-+ case Cast.castLLVMRet fnm bak ret ret' of+ Left err ->+ panic "Intrinsics.build_llvm_override"+ (Cast.printValCastError err +++ [ "in function: " ++ Text.unpack (functionName fnm) ])+ Right f -> pure f return $ mkOverride' fnm ret' $ do RegMap xs <- getOverrideArgs- ovrWithBackend $ \bak' ->- applyValTransformer fret =<< llvmOverride bak' =<< applyArgTransformer fargs xs+ Cast.applyValCast fret =<< llvmOverride =<< Cast.applyArgCast fargs xs -polymorphic1_llvm_override :: forall p sym arch wptr l a rtp.+polymorphic1_llvm_override :: forall p sym ext arch wptr. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => String ->- (forall w. (1 <= w) => NatRepr w -> SomeLLVMOverride p sym) ->- OverrideTemplate p sym arch rtp l a+ (forall w. (1 <= w) => NatRepr w -> SomeLLVMOverride p sym ext) ->+ OverrideTemplate p sym ext arch polymorphic1_llvm_override prefix fn =- OverrideTemplate (PrefixMatch prefix) (register_1arg_polymorphic_override prefix fn)+ OverrideTemplate (Match.PrefixMatch prefix) (register_1arg_polymorphic_override prefix fn) -register_1arg_polymorphic_override :: forall p sym arch wptr l a rtp.+-- | Create an 'OverrideTemplate' for a polymorphic LLVM override involving+-- a vector type. For example, the @llvm.vector.reduce.add.*@ intrinsic can be+-- instantiated at multiple types, including:+--+-- * @i32 \@llvm.vector.reduce.add.v4i32(<4 x i32>)@+--+-- * @i64 \@llvm.vector.reduce.add.v2i64(<2 x i64>)@+--+-- * etc.+--+-- Note that the intrinsic can vary both by the size of the vector type (@4@,+-- @2@, etc.) and the size of the integer type used as the vector element type+-- (@i32@, @i64@, etc.) Therefore, the @fn@ argument that this function accepts+-- is parameterized by both the vector size (@vecSz@) and the integer size+-- (@intSz@).+polymorphic1_vec_llvm_override :: forall p sym ext arch wptr. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => String ->- (forall w. (1 <= w) => NatRepr w -> SomeLLVMOverride p sym) ->- RegOverrideM p sym arch rtp l a ()+ (forall vecSz intSz.+ (1 <= intSz) =>+ NatRepr vecSz ->+ NatRepr intSz ->+ SomeLLVMOverride p sym ext) ->+ OverrideTemplate p sym ext arch+polymorphic1_vec_llvm_override prefix fn =+ OverrideTemplate (Match.PrefixMatch prefix) (register_1arg_vec_polymorphic_override prefix fn)++register_1arg_polymorphic_override :: forall p sym ext arch wptr.+ (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) =>+ String ->+ (forall w. (1 <= w) => NatRepr w -> SomeLLVMOverride p sym ext) ->+ MakeOverride p sym ext arch register_1arg_polymorphic_override prefix overrideFn =- do (L.Declare{ L.decName = L.Symbol nm },_,_) <- ask- case List.stripPrefix prefix nm of- Just ('.':'i': (readDec -> (sz,[]):_))- | Some w <- mkNatRepr sz- , Just LeqProof <- isPosNat w- -> case overrideFn w of SomeLLVMOverride ovr -> register_llvm_override ovr- _ -> empty+ MakeOverride $ \(L.Declare{ L.decName = L.Symbol nm }) _ _ ->+ case List.stripPrefix prefix nm of+ Just ('.':'i': (readDec -> (sz,[]):_))+ | Some w <- mkNatRepr sz+ , Just LeqProof <- isPosNat w+ -> Just (overrideFn w)+ _ -> Nothing -basic_llvm_override :: forall p args ret sym arch wptr l a rtp.+-- | Register a polymorphic LLVM override involving a vector type. (See the+-- Haddocks for 'polymorphic1_vec_llvm_override' for details on what this+-- means.) This function is responsible for parsing the suffix in the+-- intrinsic's name, which encodes the sizes of the vector and integer types.+-- As some examples:+--+-- * @.v4i32@ (vector size @4@, integer size @32@)+--+-- * @.v2i64@ (vector size @2@, integer size @64@)+register_1arg_vec_polymorphic_override :: forall p sym ext arch wptr. (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) =>- LLVMOverride p sym args ret ->- OverrideTemplate p sym arch rtp l a-basic_llvm_override ovr = OverrideTemplate (ExactMatch nm) (register_llvm_override ovr)- where L.Symbol nm = L.decName (llvmOverride_declare ovr)+ String ->+ (forall vecSz intSz.+ (1 <= intSz) =>+ NatRepr vecSz ->+ NatRepr intSz ->+ SomeLLVMOverride p sym ext) ->+ MakeOverride p sym ext arch+register_1arg_vec_polymorphic_override prefix overrideFn =+ MakeOverride $ \(L.Declare{ L.decName = L.Symbol nm }) _ _ ->+ case List.stripPrefix prefix nm of+ Just ('.':'v':suffix1)+ | (vecSzStr, 'i':intSzStr) <- break (== 'i') suffix1+ , (vecSzNat, []):_ <- readDec vecSzStr+ , (intSzNat, []):_ <- readDec intSzStr+ , Some vecSzRepr <- mkNatRepr vecSzNat+ , Some intSzRepr <- mkNatRepr intSzNat+ , Just LeqProof <- isPosNat intSzRepr+ -> Just (overrideFn vecSzRepr intSzRepr)+ _ -> Nothing +basic_llvm_override :: forall p args ret sym ext arch wptr.+ (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) =>+ LLVMOverride p sym ext args ret ->+ OverrideTemplate p sym ext arch+basic_llvm_override ovr = OverrideTemplate matcher regOvr+ where+ ovrDecl = llvmOverride_declare ovr+ L.Symbol ovrNm = L.decName ovrDecl+ isDarwin = Info.os == "darwin" + matcher :: Match.TemplateMatcher+ matcher | isDarwin = Match.DarwinAliasMatch ovrNm+ | otherwise = Match.ExactMatch ovrNm++ regOvr :: MakeOverride p sym ext arch+ regOvr = do+ MakeOverride $ \requestedDecl _ _ -> do+ let L.Symbol requestedNm = L.decName requestedDecl+ -- If we are on Darwin and the function name contains Darwin-specific+ -- prefixes or suffixes, change the name of the override to the+ -- name containing prefixes/suffixes. See Note [Darwin aliases] in+ -- Lang.Crucible.LLVM.Intrinsics.Match for an explanation of why we+ -- do this.+ let ovr' | isDarwin+ , ovrNm == Match.stripDarwinAliases requestedNm+ = ovr { llvmOverride_declare =+ ovrDecl { L.decName = L.Symbol requestedNm }}++ | otherwise+ = ovr+ Just (SomeLLVMOverride ovr')+ -- | Check that the requested declaration matches the provided declaration. In -- this context, \"matching\" means that both declarations have identical names, -- as well as equal argument and result types. When checking types for equality,@@ -277,60 +307,24 @@ matchingArgList _ [] = L.decVarArgs provided matchingArgList (x:xs) (y:ys) = x `L.eqTypeModuloOpaquePtrs` y && matchingArgList xs ys -register_llvm_override :: forall p args ret sym arch wptr l a rtp.+register_llvm_override :: forall p args ret sym ext arch wptr rtp l a. (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym) =>- LLVMOverride p sym args ret ->- RegOverrideM p sym arch rtp l a ()-register_llvm_override llvmOverride = do- (requestedDecl,_,llvmctx) <- ask+ LLVMOverride p sym ext args ret ->+ L.Declare ->+ LLVMContext arch ->+ OverrideSim p sym ext rtp l a ()+register_llvm_override llvmOverride requestedDecl llvmctx = do let decl = llvmOverride_declare llvmOverride if not (isMatchingDeclaration requestedDecl decl) then do when (L.decName requestedDecl == L.decName decl) $- do logFn <- lift $ lift $ getLogFunction+ do logFn <- getLogFunction liftIO $ logFn 3 $ unlines [ "Mismatched declaration signatures" , " *** requested: " ++ show requestedDecl , " *** found: " ++ show decl , "" ]- empty- else lift (lift (do_register_llvm_override llvmctx llvmOverride))---- | Bind a function handle, and also bind the function to the global function--- allocation in the LLVM memory.-bind_llvm_handle ::- (IsSymInterface sym, HasPtrWidth wptr) =>- LLVMContext arch ->- L.Symbol ->- FnHandle args ret ->- FnState p sym LLVM args ret ->- OverrideSim p sym LLVM rtp l a ()-bind_llvm_handle llvmCtx nm hdl impl = do- let mvar = llvmMemVar llvmCtx- bindFnHandle hdl impl- mem <- readGlobal mvar- mem' <- ovrWithBackend $ \bak -> liftIO $ bindLLVMFunPtr bak nm hdl mem- writeGlobal mvar mem'---- | Low-level function to register LLVM functions.------ Creates and binds a function handle, and also binds the function to the--- global function allocation in the LLVM memory.-bind_llvm_func ::- (IsSymInterface sym, HasPtrWidth wptr) =>- LLVMContext arch ->- L.Symbol ->- Ctx.Assignment TypeRepr args ->- TypeRepr ret ->- FnState p sym LLVM args ret ->- OverrideSim p sym LLVM rtp l a ()-bind_llvm_func llvmCtx nm args ret impl = do- let L.Symbol strNm = nm- let fnm = functionNameFromText (Text.pack strNm)- ctx <- use stateContext- let ha = simHandleAllocator ctx- h <- liftIO $ mkHandle' ha fnm args ret- bind_llvm_handle llvmCtx nm h impl+ else do_register_llvm_override llvmctx llvmOverride -- | Low-level function to register LLVM overrides. --@@ -342,11 +336,11 @@ -- Useful when you don\'t have access to a full LLVM AST, e.g., when parsing -- Crucible CFGs written in crucible-syntax. For more usual cases, use -- 'Lang.Crucible.LLVM.Intrinsics.register_llvm_overrides'.-do_register_llvm_override :: forall p args ret sym arch wptr l a rtp.+do_register_llvm_override :: forall p args ret sym ext arch wptr l a rtp. (IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym) => LLVMContext arch ->- LLVMOverride p sym args ret ->- OverrideSim p sym LLVM rtp l a ()+ LLVMOverride p sym ext args ret ->+ OverrideSim p sym ext rtp l a () do_register_llvm_override llvmctx llvmOverride = do let decl = llvmOverride_declare llvmOverride let (L.Symbol str_nm) = L.decName decl@@ -360,8 +354,8 @@ llvmDeclToFunHandleRepr' decl $ \args ret -> do o <- build_llvm_override fnm overrideArgs overrideRet args ret- (\bak asgn -> llvmOverride_def llvmOverride mvar bak asgn)- bind_llvm_func llvmctx (L.decName decl) args ret (UseOverride o)+ (\asgn -> llvmOverride_def llvmOverride mvar asgn)+ bindLLVMFunc mvar (L.decName decl) args ret (UseOverride o) -- | Create an allocation for an override and register it. --@@ -375,7 +369,7 @@ (IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym, ?memOpts :: MemOptions) => bak -> LLVMContext arch ->- LLVMOverride p sym args ret ->+ LLVMOverride p sym LLVM args ret -> -- | Aliases [L.Symbol] -> OverrideSim p sym LLVM rtp l a ()
src/Lang/Crucible/LLVM/Intrinsics/LLVM.hs view
@@ -51,1523 +51,2092 @@ import Lang.Crucible.Simulator.RegMap import Lang.Crucible.Simulator.SimError (SimErrorReason(AssertFailureSimError)) -import Lang.Crucible.LLVM.Bytes (Bytes(..))-import Lang.Crucible.LLVM.DataLayout (noAlignment)-import Lang.Crucible.LLVM.MemModel-import Lang.Crucible.LLVM.QQ( llvmOvr )--import Lang.Crucible.LLVM.Intrinsics.Common-import qualified Lang.Crucible.LLVM.Intrinsics.Libc as Libc----------------------------------------------------------------------------- ** Declarations---- | This intrinsic is currently a no-op.------ We might want to support this in the future to catch undefined memory--- accesses.------ <https://llvm.org/docs/LangRef.html#llvm-lifetime-start-intrinsic LLVM docs>-llvmLifetimeStartOverride- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr) UnitType-llvmLifetimeStartOverride =- [llvmOvr| void @llvm.lifetime.start( i64, i8* ) |]- (\_ops _sym _args -> return ())---- | See comment on 'llvmLifetimeStartOverride'------ <https://llvm.org/docs/LangRef.html#llvm-lifetime-end-intrinsic LLVM docs>-llvmLifetimeEndOverride- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr) UnitType-llvmLifetimeEndOverride =- [llvmOvr| void @llvm.lifetime.end( i64, i8* ) |]- (\_ops _sym _args -> return ())---- | This is a no-op.------ The language reference doesn't mention the use of this intrinsic.-llvmLifetimeOverrideOverload- :: forall width sym wptr p- . ( 1 <= width, KnownNat width- , IsSymInterface sym, HasPtrWidth wptr)- => String -- ^ "start" or "end"- -> NatRepr width- -> LLVMOverride p sym- (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr)- UnitType -- It appears in practice that this is always void-llvmLifetimeOverrideOverload startOrEnd w =- let nm = L.Symbol ("llvm.lifetime." ++ startOrEnd ++ ".p0i" ++ show (widthVal w)) in- [llvmOvr| void $nm ( i64, #w * ) |]- (\_ops _sym _args -> return ())---- | Like 'llvmLifetimeOverrideOverload', but with an opaque pointer type.-llvmLifetimeOverrideOverload_opaque- :: forall sym wptr p- . (IsSymInterface sym, HasPtrWidth wptr)- => String -- ^ "start" or "end"- -> LLVMOverride p sym- (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr)- UnitType -- It appears in practice that this is always void-llvmLifetimeOverrideOverload_opaque startOrEnd =- let nm = L.Symbol ("llvm.lifetime." ++ startOrEnd ++ ".p0") in- [llvmOvr| void $nm ( i64, ptr ) |]- (\_ops _sym _args -> return ())---- | This intrinsic is currently a no-op.------ We might want to support this in the future to catch undefined memory--- writes.------ <https://llvm.org/docs/LangRef.html#llvm-invariant-start-intrinsic LLVM docs>-llvmInvariantStartOverride- :: (IsSymInterface sym, HasPtrWidth wptr)- => NatRepr width- -> LLVMOverride p sym- (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr)- (LLVMPointerType wptr)-llvmInvariantStartOverride w =- let nm = L.Symbol ("llvm.invariant.start.p0i" ++ show (widthVal w)) in- [llvmOvr| {}* $nm ( i64, #w * ) |]- (\_ops bak _args -> liftIO (mkNullPointer (backendGetSym bak) PtrWidth))---- | Like 'llvmInvariantStartOverride', but with an opaque pointer type.-llvmInvariantStartOverride_opaque- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr)- (LLVMPointerType wptr)-llvmInvariantStartOverride_opaque =- let nm = L.Symbol "llvm.invariant.start.p0" in- [llvmOvr| {}* $nm ( i64, ptr ) |]- (\_ops bak _args -> liftIO (mkNullPointer (backendGetSym bak) PtrWidth))---- | See comment on 'llvmInvariantStartOverride'.-llvmInvariantEndOverride- :: (IsSymInterface sym, HasPtrWidth wptr)- => NatRepr width- -> LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> BVType 64 ::> LLVMPointerType wptr)- UnitType-llvmInvariantEndOverride w =- let nm = L.Symbol ("llvm.invariant.end.p0i" ++ show (widthVal w)) in- [llvmOvr| void $nm ( {}*, i64, #w * ) |]- (\_ops _bak _args -> return ())---- | See comment on 'llvmInvariantStartOverride_opaque'.-llvmInvariantEndOverride_opaque- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> BVType 64 ::> LLVMPointerType wptr)- UnitType-llvmInvariantEndOverride_opaque =- let nm = L.Symbol "llvm.invariant.end.p0" in- [llvmOvr| void $nm ( {}*, i64, ptr ) |]- (\_ops _bak _args -> return ())---- | This instruction is a hint to optimizers, it isn't really useful for us.------ Its runtime behavior of that of Haskell\'s 'const': just ignore the second--- argument.-llvmExpectOverride- :: (IsSymInterface sym, 1 <= width)- => NatRepr width- -> LLVMOverride p sym- (EmptyCtx ::> BVType width ::> BVType width)- (BVType width)-llvmExpectOverride w =- let nm = L.Symbol ("llvm.expect.i" ++ show (widthVal w)) in- [llvmOvr| #w $nm ( #w, #w ) |]- (\_ops _bak args ->- Ctx.uncurryAssignment (\val _ -> pure (regValue val)) args)---- | This intrinsic asserts that its argument is equal to 1.------ We could have this generate a verification condition, but that would catch--- clang compiler bugs (or Crucible bugs) more than user code bugs.-llvmAssumeOverride- :: (IsSymInterface sym)- => LLVMOverride p sym (EmptyCtx ::> BVType 1) UnitType-llvmAssumeOverride =- [llvmOvr| void @llvm.assume ( i1 ) |]- (\_ops _bak _args -> return ())---- | This intrinsic is sometimes inserted by clang, and we interpret it--- as an assertion failure, similar to calling @abort()@.-llvmTrapOverride- :: (IsSymInterface sym)- => LLVMOverride p sym EmptyCtx UnitType-llvmTrapOverride =- [llvmOvr| void @llvm.trap() |]- (\_ops bak _args -> liftIO $ addFailedAssertion bak $ AssertFailureSimError "llvm.trap() called" "")---- | This is like @llvm.trap()@, but with an argument indicating which sort of--- undefined behavior was trapped. The argument acts as an index into--- <https://github.com/llvm/llvm-project/blob/650bbc56203c947bb85176c40ca9c7c7a91c3c57/clang/lib/CodeGen/CodeGenFunction.h#L118-L143 this list>.--- Ideally, we would do something intelligent with this argument—see #368.-llvmUBSanTrapOverride ::- IsSymInterface sym =>- LLVMOverride p sym (EmptyCtx ::> BVType 8) UnitType-llvmUBSanTrapOverride =- [llvmOvr| void @llvm.ubsantrap( i8 ) |]- (\_ops bak _args -> liftIO $ addFailedAssertion bak $ AssertFailureSimError "llvm.ubsantrap() called" "")--llvmStacksave- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym EmptyCtx (LLVMPointerType wptr)-llvmStacksave =- [llvmOvr| i8* @llvm.stacksave() |]- (\_memOps bak _args -> liftIO (mkNullPointer (backendGetSym bak) PtrWidth))--llvmStackrestore- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr) UnitType-llvmStackrestore =- [llvmOvr| void @llvm.stackrestore( i8* ) |]- (\_memOps _bak _args -> return ())--llvmMemmoveOverride_8_8_32- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 32 ::> BVType 32 ::> BVType 1)- UnitType-llvmMemmoveOverride_8_8_32 =- [llvmOvr| void @llvm.memmove.p0i8.p0i8.i32( i8*, i8*, i32, i32, i1 ) |]- (\memOps bak args ->- Ctx.uncurryAssignment (\dst src len _align v -> Libc.callMemmove bak memOps dst src len v) args)--llvmMemmoveOverride_8_8_32_noalign- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 32 ::> BVType 1)- UnitType-llvmMemmoveOverride_8_8_32_noalign =- [llvmOvr| void @llvm.memmove.p0i8.p0i8.i32( i8*, i8*, i32, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (Libc.callMemmove bak memOps) args)--llvmMemmoveOverride_8_8_32_noalign_opaque- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 32 ::> BVType 1)- UnitType-llvmMemmoveOverride_8_8_32_noalign_opaque =- [llvmOvr| void @llvm.memmove.p0.p0.i32( ptr, ptr, i32, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (Libc.callMemmove bak memOps) args)---llvmMemmoveOverride_8_8_64- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 64 ::> BVType 32 ::> BVType 1)- UnitType-llvmMemmoveOverride_8_8_64 =- [llvmOvr| void @llvm.memmove.p0i8.p0i8.i64( i8*, i8*, i64, i32, i1 ) |]- (\memOps bak args ->- Ctx.uncurryAssignment (\dst src len _align v -> Libc.callMemmove bak memOps dst src len v) args)--llvmMemmoveOverride_8_8_64_noalign- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 64 ::> BVType 1)- UnitType-llvmMemmoveOverride_8_8_64_noalign =- [llvmOvr| void @llvm.memmove.p0i8.p0i8.i64( i8*, i8*, i64, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (Libc.callMemmove bak memOps) args)--llvmMemmoveOverride_8_8_64_noalign_opaque- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 64 ::> BVType 1)- UnitType-llvmMemmoveOverride_8_8_64_noalign_opaque =- [llvmOvr| void @llvm.memmove.p0.p0.i64( ptr, ptr, i64, i1 ) |]- (\memOps bak args ->- Ctx.uncurryAssignment (Libc.callMemmove bak memOps) args)---llvmMemsetOverride_8_64- :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> BVType 8- ::> BVType 64- ::> BVType 32- ::> BVType 1)- UnitType-llvmMemsetOverride_8_64 =- [llvmOvr| void @llvm.memset.p0i8.i64( i8*, i8, i64, i32, i1 ) |]- (\memOps bak args ->- Ctx.uncurryAssignment (\dst val len _align v -> Libc.callMemset bak memOps dst val len v) args)--llvmMemsetOverride_8_64_noalign- :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> BVType 8- ::> BVType 64- ::> BVType 1)- UnitType-llvmMemsetOverride_8_64_noalign =- [llvmOvr| void @llvm.memset.p0i8.i64( i8*, i8, i64, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (Libc.callMemset bak memOps) args)--llvmMemsetOverride_8_64_noalign_opaque- :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> BVType 8- ::> BVType 64- ::> BVType 1)- UnitType-llvmMemsetOverride_8_64_noalign_opaque =- [llvmOvr| void @llvm.memset.p0.i64( ptr, i8, i64, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (Libc.callMemset bak memOps) args)---llvmMemsetOverride_8_32- :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> BVType 8- ::> BVType 32- ::> BVType 32- ::> BVType 1)- UnitType-llvmMemsetOverride_8_32 =- [llvmOvr| void @llvm.memset.p0i8.i32( i8*, i8, i32, i32, i1 ) |]- (\memOps bak args ->- Ctx.uncurryAssignment (\dst val len _align v -> Libc.callMemset bak memOps dst val len v) args)--llvmMemsetOverride_8_32_noalign- :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> BVType 8- ::> BVType 32- ::> BVType 1)- UnitType-llvmMemsetOverride_8_32_noalign =- [llvmOvr| void @llvm.memset.p0i8.i32( i8*, i8, i32, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (Libc.callMemset bak memOps) args)--llvmMemsetOverride_8_32_noalign_opaque- :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> BVType 8- ::> BVType 32- ::> BVType 1)- UnitType-llvmMemsetOverride_8_32_noalign_opaque =- [llvmOvr| void @llvm.memset.p0.i32( ptr, i8, i32, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (Libc.callMemset bak memOps) args)---llvmMemcpyOverride_8_8_32- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 32 ::> BVType 32 ::> BVType 1)- UnitType-llvmMemcpyOverride_8_8_32 =- [llvmOvr| void @llvm.memcpy.p0i8.p0i8.i32( i8*, i8*, i32, i32, i1 ) |]- (\memOps bak args ->- Ctx.uncurryAssignment (\dst src len _align v -> Libc.callMemcpy bak memOps dst src len v) args)--llvmMemcpyOverride_8_8_32_noalign- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 32 ::> BVType 1)- UnitType-llvmMemcpyOverride_8_8_32_noalign =- [llvmOvr| void @llvm.memcpy.p0i8.p0i8.i32( i8*, i8*, i32, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (Libc.callMemcpy bak memOps) args)--llvmMemcpyOverride_8_8_32_noalign_opaque- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 32 ::> BVType 1)- UnitType-llvmMemcpyOverride_8_8_32_noalign_opaque =- [llvmOvr| void @llvm.memcpy.p0.p0.i32( ptr, ptr, i32, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (Libc.callMemcpy bak memOps) args)---llvmMemcpyOverride_8_8_64- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 64 ::> BVType 32 ::> BVType 1)- UnitType-llvmMemcpyOverride_8_8_64 =- [llvmOvr| void @llvm.memcpy.p0i8.p0i8.i64( i8*, i8*, i64, i32, i1 ) |]- (\memOps bak args ->- Ctx.uncurryAssignment (\dst src len _align v -> Libc.callMemcpy bak memOps dst src len v) args)--llvmMemcpyOverride_8_8_64_noalign- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 64 ::> BVType 1)- UnitType-llvmMemcpyOverride_8_8_64_noalign =- [llvmOvr| void @llvm.memcpy.p0i8.p0i8.i64( i8*, i8*, i64, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (Libc.callMemcpy bak memOps) args)--llvmMemcpyOverride_8_8_64_noalign_opaque- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr- ::> BVType 64 ::> BVType 1)- UnitType-llvmMemcpyOverride_8_8_64_noalign_opaque =- [llvmOvr| void @llvm.memcpy.p0.p0.i64( ptr, ptr, i64, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (Libc.callMemcpy bak memOps) args)---llvmObjectsizeOverride_32- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1) (BVType 32)-llvmObjectsizeOverride_32 =- [llvmOvr| i32 @llvm.objectsize.i32.p0i8( i8*, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callObjectsize bak memOps knownNat) args)--llvmObjectsizeOverride_32_null- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1) (BVType 32)-llvmObjectsizeOverride_32_null =- [llvmOvr| i32 @llvm.objectsize.i32.p0i8( i8*, i1, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callObjectsize_null bak memOps knownNat) args)--llvmObjectsizeOverride_32_null_dynamic- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1 ::> BVType 1) (BVType 32)-llvmObjectsizeOverride_32_null_dynamic =- [llvmOvr| i32 @llvm.objectsize.i32.p0i8( i8*, i1, i1, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callObjectsize_null_dynamic bak memOps knownNat) args)--llvmObjectsizeOverride_32_null_dynamic_opaque- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1 ::> BVType 1) (BVType 32)-llvmObjectsizeOverride_32_null_dynamic_opaque =- [llvmOvr| i32 @llvm.objectsize.i32.p0( ptr, i1, i1, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callObjectsize_null_dynamic bak memOps knownNat) args)--llvmObjectsizeOverride_64- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1) (BVType 64)-llvmObjectsizeOverride_64 =- [llvmOvr| i64 @llvm.objectsize.i64.p0i8( i8*, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callObjectsize bak memOps knownNat) args)--llvmObjectsizeOverride_64_null- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1) (BVType 64)-llvmObjectsizeOverride_64_null =- [llvmOvr| i64 @llvm.objectsize.i64.p0i8( i8*, i1, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callObjectsize_null bak memOps knownNat) args)--llvmObjectsizeOverride_64_null_dynamic- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1 ::> BVType 1) (BVType 64)-llvmObjectsizeOverride_64_null_dynamic =- [llvmOvr| i64 @llvm.objectsize.i64.p0i8( i8*, i1, i1, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callObjectsize_null_dynamic bak memOps knownNat) args)--llvmObjectsizeOverride_64_null_dynamic_opaque- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1 ::> BVType 1) (BVType 64)-llvmObjectsizeOverride_64_null_dynamic_opaque =- [llvmOvr| i64 @llvm.objectsize.i64.p0( ptr, i1, i1, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callObjectsize_null_dynamic bak memOps knownNat) args)---- | This instruction is a hint to code generators, which means that it is a--- no-op for us.------ <https://releases.llvm.org/12.0.0/docs/LangRef.html#llvm-prefetch-intrinsic LLVM docs>-llvmPrefetchOverride ::- (IsSymInterface sym, HasPtrWidth wptr) =>- LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> BVType 32 ::> BVType 32 ::> BVType 32)- UnitType-llvmPrefetchOverride =- [llvmOvr| void @llvm.prefetch.p0i8( i8*, i32, i32, i32 ) |]- (\_memOps _bak _args -> pure ())---- | Like 'llvmPrefetchOverride', but with an opaque pointer type.-llvmPrefetchOverride_opaque ::- (IsSymInterface sym, HasPtrWidth wptr) =>- LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> BVType 32 ::> BVType 32 ::> BVType 32)- UnitType-llvmPrefetchOverride_opaque =- [llvmOvr| void @llvm.prefetch.p0( ptr, i32, i32, i32 ) |]- (\_memOps _bak _args -> pure ())---- | This instruction is a hint to code generators, which means that it is a--- no-op for us.------ See also 'llvmPrefetchOverride'. This version exists for compatibility with--- pre-10 versions of LLVM, where llvm.prefetch always assumed that the first--- argument resides in address space 0.------ <https://releases.llvm.org/12.0.0/docs/LangRef.html#llvm-prefetch-intrinsic LLVM docs>-llvmPrefetchOverride_preLLVM10 ::- (IsSymInterface sym, HasPtrWidth wptr) =>- LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> BVType 32 ::> BVType 32 ::> BVType 32)- UnitType-llvmPrefetchOverride_preLLVM10 =- [llvmOvr| void @llvm.prefetch( i8*, i32, i32, i32 ) |]- (\_memOps _bak _args -> pure ())--llvmFshl ::- (1 <= w, IsSymInterface sym) =>- NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w ::> BVType w)- (BVType w)-llvmFshl w =- let nm = L.Symbol ("llvm.fshl.i" ++ show (natValue w)) in- [llvmOvr| #w $nm ( #w, #w, #w ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callFshl bak w) args)--llvmFshr ::- (1 <= w, IsSymInterface sym) =>- NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w ::> BVType w)- (BVType w)-llvmFshr w =- let nm = L.Symbol ("llvm.fshr.i" ++ show (natValue w)) in- [llvmOvr| #w $nm ( #w, #w, #w ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callFshr bak w) args)--llvmSaddWithOverflow- :: (1 <= w, IsSymInterface sym)- => NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w)- (StructType (EmptyCtx ::> BVType w ::> BVType 1))-llvmSaddWithOverflow w =- let nm = L.Symbol ("llvm.sadd.with.overflow.i" ++ show (natValue w)) in- [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callSaddWithOverflow bak memOps) args)--llvmUaddWithOverflow- :: (1 <= w, IsSymInterface sym)- => NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w)- (StructType (EmptyCtx ::> BVType w ::> BVType 1))-llvmUaddWithOverflow w =- let nm = L.Symbol ("llvm.uadd.with.overflow.i" ++ show (natValue w)) in- [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callUaddWithOverflow bak memOps) args)---llvmSsubWithOverflow- :: (1 <= w, IsSymInterface sym)- => NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w)- (StructType (EmptyCtx ::> BVType w ::> BVType 1))-llvmSsubWithOverflow w =- let nm = L.Symbol ("llvm.ssub.with.overflow.i" ++ show (natValue w)) in- [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callSsubWithOverflow bak memOps) args)---llvmUsubWithOverflow- :: (1 <= w, IsSymInterface sym)- => NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w)- (StructType (EmptyCtx ::> BVType w ::> BVType 1))-llvmUsubWithOverflow w =- let nm = L.Symbol ("llvm.usub.with.overflow.i" ++ show (natValue w)) in- [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callUsubWithOverflow bak memOps) args)--llvmSmulWithOverflow- :: (1 <= w, IsSymInterface sym)- => NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w)- (StructType (EmptyCtx ::> BVType w ::> BVType 1))-llvmSmulWithOverflow w =- let nm = L.Symbol ("llvm.smul.with.overflow.i" ++ show (natValue w)) in- [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callSmulWithOverflow bak memOps) args)--llvmUmulWithOverflow- :: (1 <= w, IsSymInterface sym)- => NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w)- (StructType (EmptyCtx ::> BVType w ::> BVType 1))-llvmUmulWithOverflow w =- let nm = L.Symbol ("llvm.umul.with.overflow.i" ++ show (natValue w)) in- [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callUmulWithOverflow bak memOps) args)--llvmUmax ::- (1 <= w, IsSymInterface sym) =>- NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w)- (BVType w)-llvmUmax w =- let nm = L.Symbol ("llvm.umax.i" ++ show (natValue w)) in- [llvmOvr| #w $nm( #w, #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callUmax bak memOps) args)--llvmUmin ::- (1 <= w, IsSymInterface sym) =>- NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w)- (BVType w)-llvmUmin w =- let nm = L.Symbol ("llvm.umin.i" ++ show (natValue w)) in- [llvmOvr| #w $nm( #w, #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callUmin bak memOps) args)--llvmSmax ::- (1 <= w, IsSymInterface sym) =>- NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w)- (BVType w)-llvmSmax w =- let nm = L.Symbol ("llvm.smax.i" ++ show (natValue w)) in- [llvmOvr| #w $nm( #w, #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callSmax bak memOps) args)--llvmSmin ::- (1 <= w, IsSymInterface sym) =>- NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType w)- (BVType w)-llvmSmin w =- let nm = L.Symbol ("llvm.smin.i" ++ show (natValue w)) in- [llvmOvr| #w $nm( #w, #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callSmin bak memOps) args)--llvmCtlz- :: (1 <= w, IsSymInterface sym)- => NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType 1)- (BVType w)-llvmCtlz w =- let nm = L.Symbol ("llvm.ctlz.i" ++ show (natValue w)) in- [llvmOvr| #w $nm ( #w, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callCtlz bak memOps) args)--llvmCttz- :: (1 <= w, IsSymInterface sym)- => NatRepr w- -> LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType 1)- (BVType w)-llvmCttz w =- let nm = L.Symbol ("llvm.cttz.i" ++ show (natValue w)) in- [llvmOvr| #w $nm ( #w, i1 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callCttz bak memOps) args)--llvmCtpop- :: (1 <= w, IsSymInterface sym)- => NatRepr w- -> LLVMOverride p sym- (EmptyCtx ::> BVType w)- (BVType w)-llvmCtpop w =- let nm = L.Symbol ("llvm.ctpop.i" ++ show (natValue w)) in- [llvmOvr| #w $nm( #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callCtpop bak memOps) args)--llvmBitreverse- :: (1 <= w, IsSymInterface sym)- => NatRepr w- -> LLVMOverride p sym- (EmptyCtx ::> BVType w)- (BVType w)-llvmBitreverse w =- let nm = L.Symbol ("llvm.bitreverse.i" ++ show (natValue w)) in- [llvmOvr| #w $nm( #w ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callBitreverse bak memOps) args)---- | <https://llvm.org/docs/LangRef.html#llvm-bswap-intrinsics LLVM docs>-llvmBSwapOverride- :: forall width sym p- . ( 1 <= width, IsSymInterface sym)- => NatRepr width- -> LLVMOverride p sym- (EmptyCtx ::> BVType (width * 8))- (BVType (width * 8))-llvmBSwapOverride widthRepr =- let width8 = natMultiply widthRepr (knownNat @8)- nm = L.Symbol ("llvm.bswap.i" ++ show (widthVal width8))- in- case mulComm widthRepr (knownNat @8) of { Refl ->- case leqMulMono (knownNat @8) widthRepr :: LeqProof width (width * 8) of { LeqProof ->- case leqTrans (LeqProof :: LeqProof 1 width)- (LeqProof :: LeqProof width (width * 8)) of { LeqProof ->- -- From the LLVM docs:- -- declare i16 @llvm.bswap.i16(i16 <id>)- [llvmOvr| #width8 $nm( #width8 ) |]- (\_ bak args -> Ctx.uncurryAssignment (Libc.callBSwap bak widthRepr) args)- }}}--llvmAbsOverride ::- (1 <= w, IsSymInterface sym, HasLLVMAnn sym) =>- NatRepr w ->- LLVMOverride p sym- (EmptyCtx ::> BVType w ::> BVType 1)- (BVType w)-llvmAbsOverride w =- let nm = L.Symbol ("llvm.abs.i" ++ show (natValue w)) in- [llvmOvr| #w $nm( #w, i1 ) |]- (\mvar bak args ->- do callStack <- callStackFromMemVar' mvar- Ctx.uncurryAssignment (Libc.callLLVMAbs bak callStack w) args)--llvmCopysignOverride_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmCopysignOverride_F32 =- [llvmOvr| float @llvm.copysign.f32( float, float ) |]- (\_memOpts bak args -> Ctx.uncurryAssignment (callCopysign bak) args)--llvmCopysignOverride_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmCopysignOverride_F64 =- [llvmOvr| double @llvm.copysign.f64( double, double ) |]- (\_memOpts bak args -> Ctx.uncurryAssignment (callCopysign bak) args)---llvmFabsF32- :: forall sym p- . ( IsSymInterface sym)- => LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmFabsF32 =- [llvmOvr| float @llvm.fabs.f32( float ) |]- (\_memOps bak (Empty :> (regValue -> x)) -> liftIO (iFloatAbs @_ @SingleFloat (backendGetSym bak) x))---llvmFabsF64- :: forall sym p- . ( IsSymInterface sym)- => LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmFabsF64 =- [llvmOvr| double @llvm.fabs.f64( double ) |]- (\_memOps bak (Empty :> (regValue -> x)) -> liftIO (iFloatAbs @_ @DoubleFloat (backendGetSym bak) x))--llvmCeilOverride_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmCeilOverride_F32 =- [llvmOvr| float @llvm.ceil.f32( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callCeil bak) args)--llvmCeilOverride_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmCeilOverride_F64 =- [llvmOvr| double @llvm.ceil.f64( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callCeil bak) args)--llvmFloorOverride_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmFloorOverride_F32 =- [llvmOvr| float @llvm.floor.f32( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callFloor bak) args)--llvmFloorOverride_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmFloorOverride_F64 =- [llvmOvr| double @llvm.floor.f64( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callFloor bak) args)--llvmSqrtOverride_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmSqrtOverride_F32 =- [llvmOvr| float @llvm.sqrt.f32( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSqrt bak) args)--llvmSqrtOverride_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmSqrtOverride_F64 =- [llvmOvr| double @llvm.sqrt.f64( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSqrt bak) args)--llvmSinOverride_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmSinOverride_F32 =- [llvmOvr| float @llvm.sin.f32( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Sin) args)--llvmSinOverride_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmSinOverride_F64 =- [llvmOvr| double @llvm.sin.f64( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Sin) args)--llvmCosOverride_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmCosOverride_F32 =- [llvmOvr| float @llvm.cos.f32( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Cos) args)--llvmCosOverride_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmCosOverride_F64 =- [llvmOvr| double @llvm.cos.f64( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Cos) args)--llvmPowOverride_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmPowOverride_F32 =- [llvmOvr| float @llvm.pow.f32( float, float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction2 bak W4.Pow) args)--llvmPowOverride_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmPowOverride_F64 =- [llvmOvr| double @llvm.pow.f64( double, double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction2 bak W4.Pow) args)--llvmExpOverride_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmExpOverride_F32 =- [llvmOvr| float @llvm.exp.f32( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Exp) args)--llvmExpOverride_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmExpOverride_F64 =- [llvmOvr| double @llvm.exp.f64( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Exp) args)--llvmLogOverride_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmLogOverride_F32 =- [llvmOvr| float @llvm.log.f32( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Log) args)--llvmLogOverride_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmLogOverride_F64 =- [llvmOvr| double @llvm.log.f64( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Log) args)--llvmExp2Override_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmExp2Override_F32 =- [llvmOvr| float @llvm.exp2.f32( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Exp2) args)--llvmExp2Override_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmExp2Override_F64 =- [llvmOvr| double @llvm.exp2.f64( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Exp2) args)--llvmLog2Override_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmLog2Override_F32 =- [llvmOvr| float @llvm.log2.f32( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Log2) args)--llvmLog2Override_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmLog2Override_F64 =- [llvmOvr| double @llvm.log2.f64( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Log2) args)--llvmLog10Override_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmLog10Override_F32 =- [llvmOvr| float @llvm.log10.f32( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Log10) args)--llvmLog10Override_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmLog10Override_F64 =- [llvmOvr| double @llvm.log10.f64( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 bak W4.Log10) args)--llvmIsFpclassOverride_F32 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat- ::> BVType 32)- (BVType 1)-llvmIsFpclassOverride_F32 =- [llvmOvr| i1 @llvm.is.fpclass.f32( float, i32 ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callIsFpclass bak) args)--llvmIsFpclassOverride_F64 ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat- ::> BVType 32)- (BVType 1)-llvmIsFpclassOverride_F64 =- [llvmOvr| i1 @llvm.is.fpclass.f64( double, i32 ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callIsFpclass bak) args)--llvmFmaOverride_F32 ::- forall sym p- . IsSymInterface sym- => LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat- ::> FloatType SingleFloat- ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmFmaOverride_F32 =- [llvmOvr| float @llvm.fma.f32( float, float, float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callFMA bak) args)--llvmFmaOverride_F64 ::- forall sym p- . IsSymInterface sym- => LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat- ::> FloatType DoubleFloat- ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmFmaOverride_F64 =- [llvmOvr| double @llvm.fma.f64( double, double, double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callFMA bak) args)--llvmFmuladdOverride_F32 ::- forall sym p- . IsSymInterface sym- => LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat- ::> FloatType SingleFloat- ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmFmuladdOverride_F32 =- [llvmOvr| float @llvm.fmuladd.f32( float, float, float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callFMA bak) args)--llvmFmuladdOverride_F64 ::- forall sym p- . IsSymInterface sym- => LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat- ::> FloatType DoubleFloat- ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmFmuladdOverride_F64 =- [llvmOvr| double @llvm.fmuladd.f64( double, double, double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (Libc.callFMA bak) args)---llvmX86_pclmulqdq---declare <2 x i64> @llvm.x86.pclmulqdq(<2 x i64>, <2 x i64>, i8) #1- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> VectorType (BVType 64)- ::> VectorType (BVType 64)- ::> BVType 8)- (VectorType (BVType 64))-llvmX86_pclmulqdq =- [llvmOvr| <2 x i64> @llvm.x86.pclmulqdq(<2 x i64>, <2 x i64>, i8) |]- (\memOps bak args -> Ctx.uncurryAssignment (callX86_pclmulqdq bak memOps) args)---llvmX86_SSE2_storeu_dq- :: ( IsSymInterface sym- , HasLLVMAnn sym- , HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> VectorType (BVType 8))- UnitType-llvmX86_SSE2_storeu_dq =- [llvmOvr| void @llvm.x86.sse2.storeu.dq( i8*, <16 x i8> ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callStoreudq bak memOps) args)----------------------------------------------------------------------------- ** Implementations--callX86_pclmulqdq :: forall p sym bak ext wptr r args ret.- (IsSymBackend sym bak, HasPtrWidth wptr) =>- bak ->- GlobalVar Mem ->- RegEntry sym (VectorType (BVType 64)) ->- RegEntry sym (VectorType (BVType 64)) ->- RegEntry sym (BVType 8) ->- OverrideSim p sym ext r args ret (RegValue sym (VectorType (BVType 64)))-callX86_pclmulqdq bak _mvar- (regValue -> xs)- (regValue -> ys)- (regValue -> imm) =- do unless (V.length xs == 2) $- liftIO $ addFailedAssertion bak $ AssertFailureSimError- ("Vector length mismatch in llvm.x86.pclmulqdq intrinsic")- (unwords ["Expected <2 x i64>, but got vector of length", show (V.length xs)])- unless (V.length ys == 2) $- liftIO $ addFailedAssertion bak $ AssertFailureSimError- ("Vector length mismatch in llvm.x86.pclmulqdq intrinsic")- (unwords ["Expected <2 x i64>, but got vector of length", show (V.length ys)])- case BV.asUnsigned <$> asBV imm of- Just byte ->- do let xidx = if byte .&. 0x01 == 0 then 0 else 1- let yidx = if byte .&. 0x10 == 0 then 0 else 1- liftIO $ doPcmul (xs V.! xidx) (ys V.! yidx)- _ ->- liftIO $ addFailedAssertion bak $ AssertFailureSimError- ("Illegal selector argument to llvm.x86.pclmulqdq")- (unwords ["Expected concrete value but got", show (printSymExpr imm)])- where- sym = backendGetSym bak-- doPcmul :: SymBV sym 64 -> SymBV sym 64 -> IO (V.Vector (SymBV sym 64))- doPcmul x y =- do r <- carrylessMultiply sym x y- lo <- bvTrunc sym (knownNat @64) r- hi <- bvSelect sym (knownNat @64) (knownNat @64) r- -- NB, little endian because X86- return $ V.fromList [ lo, hi ]--callStoreudq- :: ( IsSymBackend sym bak- , HasLLVMAnn sym- , HasPtrWidth wptr- , ?memOpts :: MemOptions )- => bak- -> GlobalVar Mem- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (VectorType (BVType 8))- -> OverrideSim p sym ext r args ret ()-callStoreudq bak mvar- (regValue -> dest)- (regValue -> vec) =- do mem <- readGlobal mvar- unless (V.length vec == 16) $- liftIO $ addFailedAssertion bak $ AssertFailureSimError- ("Vector length mismatch in stored_qu intrinsic.")- (unwords ["Expected <16 x i8>, but got vector of length", show (V.length vec)])- mem' <- liftIO $ doStore- bak- mem- dest- (VectorRepr (KnownBV @8))- (arrayType 16 (bitvectorType (Bytes 1)))- noAlignment- vec- writeGlobal mvar mem'----- Excerpt from the LLVM documentation:------ The llvm.objectsize intrinsic is designed to provide information to--- the optimizers to determine at compile time whether a) an operation--- (like memcpy) will overflow a buffer that corresponds to an object,--- or b) that a runtime check for overflow isn’t necessary. An object--- in this context means an allocation of a specific class, structure,--- array, or other object.------ The llvm.objectsize intrinsic takes two arguments. The first--- argument is a pointer to or into the object. The second argument is--- a boolean and determines whether llvm.objectsize returns 0 (if--- true) or -1 (if false) when the object size is unknown. The second--- argument only accepts constants.------ The llvm.objectsize intrinsic is lowered to a constant representing--- the size of the object concerned. If the size cannot be determined--- at compile time, llvm.objectsize returns i32/i64 -1 or 0 (depending--- on the min argument).-callObjectsize- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> NatRepr w- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (BVType 1)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callObjectsize bak _mvar w- (regValue -> _ptr)- (regValue -> flag) = liftIO $ do- let sym = backendGetSym bak- -- Ignore the pointer value, and just return the value for unknown, as- -- defined by the documenatation. If an `objectsize` invocation survives- -- through compilation for us to see, that means the compiler could not- -- determine the value.- t <- bvIsNonzero sym flag- z <- bvLit sym w (BV.zero w)- n <- bvNotBits sym z -- NB: -1 is the boolean negation of zero- bvIte sym t z n--callObjectsize_null- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> NatRepr w- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (BVType 1)- -> RegEntry sym (BVType 1)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callObjectsize_null bak mvar w ptr flag _nullUnknown = callObjectsize bak mvar w ptr flag--callObjectsize_null_dynamic- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> NatRepr w- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (BVType 1)- -> RegEntry sym (BVType 1)- -> RegEntry sym (BVType 1)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callObjectsize_null_dynamic bak mvar w ptr flag _nullUnknown (regValue -> dynamic) =- do let sym = backendGetSym bak- liftIO $- do notDynamic <- notPred sym =<< bvIsNonzero sym dynamic- assert bak notDynamic (AssertFailureSimError "llvm.objectsize called with `dynamic` set to `true`" "")- callObjectsize bak mvar w ptr flag--callCtlz- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType 1)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callCtlz bak _mvar- (regValue -> val)- (regValue -> isZeroUndef) = liftIO $- do let sym = backendGetSym bak- isNonzero <- bvIsNonzero sym val- zeroOK <- notPred sym =<< bvIsNonzero sym isZeroUndef- p <- orPred sym isNonzero zeroOK- assert bak p (AssertFailureSimError "Ctlz called with disallowed zero value" "")- bvCountLeadingZeros sym val--callFshl- :: (1 <= w, IsSymBackend sym bak)- => bak- -> NatRepr w- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callFshl bak w x y amt = liftIO $- do LeqProof <- return (dblPosIsPos (leqProof (knownNat @1) w))- Just LeqProof <- return (testLeq (addNat w (knownNat @1)) (addNat w w))- let sym = backendGetSym bak-- -- concatenate the values together- xy <- bvConcat sym (regValue x) (regValue y)-- -- The shift argument is treated as an unsigned amount modulo the element size of the arguments.- m <- bvLit sym w (BV.width w)- mamt <- bvUrem sym (regValue amt) m- mamt' <- bvZext sym (addNat w w) mamt-- -- shift left, select high bits- z <- bvShl sym xy mamt'- bvSelect sym w w z--callFshr- :: (1 <= w, IsSymBackend sym bak)- => bak- -> NatRepr w- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callFshr bak w x y amt = liftIO $- do LeqProof <- return (dblPosIsPos (leqProof (knownNat @1) w))- LeqProof <- return (addPrefixIsLeq w w)- Just LeqProof <- return (testLeq (addNat w (knownNat @1)) (addNat w w))- let sym = backendGetSym bak-- -- concatenate the values together- xy <- bvConcat sym (regValue x) (regValue y)-- -- The shift argument is treated as an unsigned amount modulo the element size of the arguments.- m <- bvLit sym w (BV.width w)- mamt <- bvUrem sym (regValue amt) m- mamt' <- bvZext sym (addNat w w) mamt-- -- shift right, select low bits- z <- bvLshr sym xy mamt'- bvSelect sym (knownNat @0) w z--callSaddWithOverflow- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))-callSaddWithOverflow bak _mvar- (regValue -> x)- (regValue -> y) = liftIO $- do let sym = backendGetSym bak- (ov, z) <- addSignedOF sym x y- ov' <- predToBV sym ov (knownNat @1)- return (Empty :> RV z :> RV ov')--callUaddWithOverflow- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))-callUaddWithOverflow bak _mvar- (regValue -> x)- (regValue -> y) = liftIO $- do let sym = backendGetSym bak- (ov, z) <- addUnsignedOF sym x y- ov' <- predToBV sym ov (knownNat @1)- return (Empty :> RV z :> RV ov')--callUsubWithOverflow- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))-callUsubWithOverflow bak _mvar- (regValue -> x)- (regValue -> y) = liftIO $- do let sym = backendGetSym bak- (ov, z) <- subUnsignedOF sym x y- ov' <- predToBV sym ov (knownNat @1)- return (Empty :> RV z :> RV ov')--callSsubWithOverflow- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))-callSsubWithOverflow bak _mvar- (regValue -> x)- (regValue -> y) = liftIO $- do let sym = backendGetSym bak- (ov, z) <- subSignedOF sym x y- ov' <- predToBV sym ov (knownNat @1)- return (Empty :> RV z :> RV ov')--callSmulWithOverflow- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))-callSmulWithOverflow bak _mvar- (regValue -> x)- (regValue -> y) = liftIO $- do let sym = backendGetSym bak- (ov, z) <- mulSignedOF sym x y- ov' <- predToBV sym ov (knownNat @1)- return (Empty :> RV z :> RV ov')--callUmulWithOverflow- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))-callUmulWithOverflow bak _mvar- (regValue -> x)- (regValue -> y) = liftIO $- do let sym = backendGetSym bak- (ov, z) <- mulUnsignedOF sym x y- ov' <- predToBV sym ov (knownNat @1)- return (Empty :> RV z :> RV ov')--callUmax- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callUmax bak _mvar (regValue -> x) (regValue -> y) = liftIO $- do let sym = backendGetSym bak- xGtY <- bvUgt sym x y- bvIte sym xGtY x y--callUmin- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callUmin bak _mvar (regValue -> x) (regValue -> y) = liftIO $- do let sym = backendGetSym bak- xLtY <- bvUlt sym x y- bvIte sym xLtY x y--callSmax- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callSmax bak _mvar (regValue -> x) (regValue -> y) = liftIO $- do let sym = backendGetSym bak- xGtY <- bvSgt sym x y- bvIte sym xGtY x y--callSmin- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callSmin bak _mvar (regValue -> x) (regValue -> y) = liftIO $- do let sym = backendGetSym bak- xLtY <- bvSlt sym x y- bvIte sym xLtY x y---callCttz- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType 1)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callCttz bak _mvar- (regValue -> val)- (regValue -> isZeroUndef) = liftIO $- do let sym = backendGetSym bak- isNonzero <- bvIsNonzero sym val- zeroOK <- notPred sym =<< bvIsNonzero sym isZeroUndef- p <- orPred sym isNonzero zeroOK- assert bak p (AssertFailureSimError "Cttz called with disallowed zero value" "")- bvCountTrailingZeros sym val--callCtpop- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callCtpop bak _mvar- (regValue -> val) = liftIO $ bvPopcount (backendGetSym bak) val--callBitreverse- :: (1 <= w, IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType w)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callBitreverse bak _mvar- (regValue -> val) = liftIO $ bvBitreverse (backendGetSym bak) val---- | Strictly speaking, this doesn't quite conform to the C99 description of--- @copysign@, since @copysign(NaN, -1.0)@ should return @NaN@ with a negative--- sign bit. @libBF@ does not provide a way to distinguish between @NaN@ values--- with different sign bits, however, so @copysign@ will always turn a @NaN@--- argument into a positive, \"quiet\" @NaN@.-callCopysign ::- forall fi p sym bak ext r args ret.- (IsSymBackend sym bak) =>- bak ->- RegEntry sym (FloatType fi) ->- RegEntry sym (FloatType fi) ->- OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))-callCopysign bak- (regValue -> x)- (regValue -> y) = liftIO $ do- let sym = backendGetSym bak- xIsNeg <- iFloatIsNeg @_ @fi sym x- yIsNeg <- iFloatIsNeg @_ @fi sym y- signsSame <- eqPred sym xIsNeg yIsNeg- xNegated <- iFloatNeg @_ @fi sym x- iFloatIte @_ @fi sym signsSame x xNegated---- | An implementation of the @llvm.is.fpclass@ intrinsic. This essentially--- combines several different floating-point checks (checking for @NaN@,--- infinity, zero, etc.) into a single function. The second argument is a--- bitmask that controls which properties to check of the first argument.--- The different checks in the bitmask are described by the table here:--- <https://llvm.org/docs/LangRef.html#id1566>------ The specification requires being able to distinguish between signaling--- @NaN@s (bit 0 of the bitmask) and quit @NaN@s (bit 1 of the bitmask), but--- @crucible-llvm@ does not have the ability to do this. As a result, both--- @NaN@ checks will always return true in this implementation, regardless of--- whether they are signaling or quiet @NaN@s.-callIsFpclass ::- forall fi p sym bak ext r args ret.- IsSymBackend sym bak =>- bak ->- RegEntry sym (FloatType fi) ->- RegEntry sym (BVType 32) ->- OverrideSim p sym ext r args ret (RegValue sym (BVType 1))-callIsFpclass bak regOp@(regValue -> op) (regValue -> test) = do- bvOne <- liftIO $ bvLit sym w1 (BV.one w1)- bvZero <- liftIO $ bvLit sym w1 (BV.zero w1)-- let negative bit = liftIO $ do- isNeg <- iFloatIsNeg @_ @fi sym op- liftIO $ bvIte sym isNeg bit bvZero-- let positive bit = liftIO $ do- isPos <- iFloatIsPos @_ @fi sym op- liftIO $ bvIte sym isPos bit bvZero-- let negAndPos doCheck = liftIO $ do- check <- doCheck- checkN <- negative check- checkP <- positive check- pure (checkN, checkP)-- let callIsInf x = do- isInf <- iFloatIsInf @_ @fi sym x- bvIte sym isInf bvOne bvZero-- let callIsNormal x = do- isNorm <- iFloatIsNorm @_ @fi sym x- bvIte sym isNorm bvOne bvZero-- let callIsSubnormal x = do- isSubnorm <- iFloatIsSubnorm @_ @fi sym x- bvIte sym isSubnorm bvOne bvZero-- let callIsZero x = do- is0 <- iFloatIsZero @_ @fi sym x- bvIte sym is0 bvOne bvZero-- isNan <- Libc.callIsnan bak w1 regOp- (isInfN, isInfP) <- negAndPos $ callIsInf op- (isNormN, isNormP) <- negAndPos $ callIsNormal op- (isSubnormN, isSubnormP) <- negAndPos $ callIsSubnormal op- (isZeroN, isZeroP) <- negAndPos $ callIsZero op-- foldM- (\bits (bitNum, check) -> liftIO $ do- isBitSet <- liftIO $ testBitBV sym bitNum test- newBit <- liftIO $ bvIte sym isBitSet check bvZero- liftIO $ bvOrBits sym newBit bits)- bvZero- [ (0, isNan) -- Signaling NaN- , (1, isNan) -- Quiet NaN- , (2, isInfN) -- Negative infinity- , (3, isNormN) -- Negative normal- , (4, isSubnormN) -- Negative subnormal- , (5, isZeroN) -- Negative zero- , (6, isZeroP) -- Positive zero- , (7, isSubnormP) -- Positive subnormal- , (8, isNormP) -- Positive normal- , (9, isInfP) -- Positive infinity- ]- where- sym = backendGetSym bak- w1 = knownNat @1+import Lang.Crucible.LLVM.Bytes (Bytes(..), bitsToBytes)+import Lang.Crucible.LLVM.DataLayout (noAlignment)+import Lang.Crucible.LLVM.MemModel+import Lang.Crucible.LLVM.QQ( llvmOvr )+import Lang.Crucible.LLVM.Utils++import Lang.Crucible.LLVM.Intrinsics.Common+import qualified Lang.Crucible.LLVM.Intrinsics.Libc as Libc+import Lang.Crucible.LLVM.TypeContext (TypeContext)++-- | Local helper to make a null pointer in 'OverrideSim'+mkNull+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => OverrideSim p sym ext rtp args ret (LLVMPtr sym wptr)+mkNull = do+ sym <- getSymInterface+ liftIO (mkNullPointer sym PtrWidth)++------------------------------------------------------------------------+-- ** Lists++-- | All \"basic\"/\"monomorphic\" LLVM overrides.+--+-- Can be turned into 'Lang.Crucible.LLVM.Intrinsics.Common.OverrideTemplate's+-- via 'Lang.Crucible.LLVM.Intrinsics.Common.basic_llvm_override'.+basic_llvm_overrides ::+ ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?lc :: TypeContext, ?memOpts :: MemOptions ) =>+ [SomeLLVMOverride p sym ext]+basic_llvm_overrides =+ [ SomeLLVMOverride llvmLifetimeStartOverride+ , SomeLLVMOverride llvmLifetimeEndOverride+ , SomeLLVMOverride (llvmLifetimeOverrideOverload "start" (knownNat @8))+ , SomeLLVMOverride (llvmLifetimeOverrideOverload "end" (knownNat @8))+ , SomeLLVMOverride (llvmLifetimeOverrideOverload_opaque "start")+ , SomeLLVMOverride (llvmLifetimeOverrideOverload_opaque "end")+ , SomeLLVMOverride (llvmInvariantStartOverride (knownNat @8))+ , SomeLLVMOverride llvmInvariantStartOverride_opaque+ , SomeLLVMOverride (llvmInvariantEndOverride (knownNat @8))+ , SomeLLVMOverride llvmInvariantEndOverride_opaque++ , SomeLLVMOverride llvmAssumeOverride+ , SomeLLVMOverride llvmTrapOverride+ , SomeLLVMOverride llvmUBSanTrapOverride++ , SomeLLVMOverride llvmMemcpyOverride_8_8_32+ , SomeLLVMOverride llvmMemcpyOverride_8_8_32_noalign+ , SomeLLVMOverride llvmMemcpyOverride_8_8_32_noalign_opaque+ , SomeLLVMOverride llvmMemcpyOverride_8_8_64+ , SomeLLVMOverride llvmMemcpyOverride_8_8_64_noalign+ , SomeLLVMOverride llvmMemcpyOverride_8_8_64_noalign_opaque++ , SomeLLVMOverride llvmMemmoveOverride_8_8_32+ , SomeLLVMOverride llvmMemmoveOverride_8_8_32_noalign+ , SomeLLVMOverride llvmMemmoveOverride_8_8_32_noalign_opaque+ , SomeLLVMOverride llvmMemmoveOverride_8_8_64+ , SomeLLVMOverride llvmMemmoveOverride_8_8_64_noalign+ , SomeLLVMOverride llvmMemmoveOverride_8_8_64_noalign_opaque++ , SomeLLVMOverride llvmMemsetOverride_8_32+ , SomeLLVMOverride llvmMemsetOverride_8_32_noalign+ , SomeLLVMOverride llvmMemsetOverride_8_32_noalign_opaque+ , SomeLLVMOverride llvmMemsetOverride_8_64+ , SomeLLVMOverride llvmMemsetOverride_8_64_noalign+ , SomeLLVMOverride llvmMemsetOverride_8_64_noalign_opaque++ , SomeLLVMOverride llvmObjectsizeOverride_32+ , SomeLLVMOverride llvmObjectsizeOverride_64++ , SomeLLVMOverride llvmObjectsizeOverride_32_null+ , SomeLLVMOverride llvmObjectsizeOverride_64_null++ , SomeLLVMOverride llvmObjectsizeOverride_32_null_dynamic+ , SomeLLVMOverride llvmObjectsizeOverride_64_null_dynamic++ , SomeLLVMOverride llvmObjectsizeOverride_32_null_dynamic_opaque+ , SomeLLVMOverride llvmObjectsizeOverride_64_null_dynamic_opaque++ , SomeLLVMOverride llvmPrefetchOverride+ , SomeLLVMOverride llvmPrefetchOverride_opaque+ , SomeLLVMOverride llvmPrefetchOverride_preLLVM10++ , SomeLLVMOverride llvmStacksave+ , SomeLLVMOverride llvmStackrestore++ , SomeLLVMOverride (llvmBSwapOverride (knownNat @2)) -- 16 = 2 * 8+ , SomeLLVMOverride (llvmBSwapOverride (knownNat @4)) -- 32 = 4 * 8+ , SomeLLVMOverride (llvmBSwapOverride (knownNat @6)) -- 48 = 6 * 8+ , SomeLLVMOverride (llvmBSwapOverride (knownNat @8)) -- 64 = 8 * 8+ , SomeLLVMOverride (llvmBSwapOverride (knownNat @10)) -- 80 = 10 * 8+ , SomeLLVMOverride (llvmBSwapOverride (knownNat @12)) -- 96 = 12 * 8+ , SomeLLVMOverride (llvmBSwapOverride (knownNat @14)) -- 112 = 14 * 8+ , SomeLLVMOverride (llvmBSwapOverride (knownNat @16)) -- 128 = 16 * 8++ , SomeLLVMOverride llvmCopysignOverride_F32+ , SomeLLVMOverride llvmCopysignOverride_F64+ , SomeLLVMOverride llvmFabsF32+ , SomeLLVMOverride llvmFabsF64++ , SomeLLVMOverride llvmCeilOverride_F32+ , SomeLLVMOverride llvmCeilOverride_F64+ , SomeLLVMOverride llvmFloorOverride_F32+ , SomeLLVMOverride llvmFloorOverride_F64+ , SomeLLVMOverride llvmSqrtOverride_F32+ , SomeLLVMOverride llvmSqrtOverride_F64+ , SomeLLVMOverride llvmSinOverride_F32+ , SomeLLVMOverride llvmSinOverride_F64+ , SomeLLVMOverride llvmCosOverride_F32+ , SomeLLVMOverride llvmCosOverride_F64+ , SomeLLVMOverride llvmPowOverride_F32+ , SomeLLVMOverride llvmPowOverride_F64+ , SomeLLVMOverride llvmExpOverride_F32+ , SomeLLVMOverride llvmExpOverride_F64+ , SomeLLVMOverride llvmLogOverride_F32+ , SomeLLVMOverride llvmLogOverride_F64+ , SomeLLVMOverride llvmExp2Override_F32+ , SomeLLVMOverride llvmExp2Override_F64+ , SomeLLVMOverride llvmLog2Override_F32+ , SomeLLVMOverride llvmLog2Override_F64+ , SomeLLVMOverride llvmLog10Override_F32+ , SomeLLVMOverride llvmLog10Override_F64+ , SomeLLVMOverride llvmFmaOverride_F32+ , SomeLLVMOverride llvmFmaOverride_F64+ , SomeLLVMOverride llvmFmuladdOverride_F32+ , SomeLLVMOverride llvmFmuladdOverride_F64+ , SomeLLVMOverride llvmIsFpclassOverride_F32+ , SomeLLVMOverride llvmIsFpclassOverride_F64++ -- Some architecture-dependent intrinsics+ , SomeLLVMOverride llvmX86_SSE2_storeu_dq+ , SomeLLVMOverride llvmX86_pclmulqdq+ ]++-- | An LLVM override that is polymorphic in a single argument+newtype Poly1LLVMOverride p sym ext+ = Poly1LLVMOverride (forall w. (1 <= w) => NatRepr w -> SomeLLVMOverride p sym ext)++poly1_llvm_overrides ::+ ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?lc :: TypeContext, ?memOpts :: MemOptions ) =>+ [(String, Poly1LLVMOverride p sym ext)]+poly1_llvm_overrides =+ [ ("llvm.ctlz"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmCtlz w)+ )+ , ("llvm.cttz"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmCttz w)+ )+ , ("llvm.ctpop"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmCtpop w)+ )+ , ("llvm.bitreverse"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmBitreverse w)+ )+ , ("llvm.abs"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmAbsOverride w)+ )++ , ("llvm.fshl"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmFshl w)+ )+ , ("llvm.fshr"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmFshr w)+ )++ , ("llvm.expect"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmExpectOverride w)+ )+ , ("llvm.sadd.with.overflow"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmSaddWithOverflow w)+ )+ , ("llvm.uadd.with.overflow"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmUaddWithOverflow w)+ )+ , ("llvm.ssub.with.overflow"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmSsubWithOverflow w)+ )+ , ("llvm.usub.with.overflow"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmUsubWithOverflow w)+ )+ , ("llvm.smul.with.overflow"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmSmulWithOverflow w)+ )+ , ("llvm.umul.with.overflow"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmUmulWithOverflow w)+ )++ , ("llvm.smax"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmSmax w)+ )+ , ("llvm.smin"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmSmin w)+ )+ , ("llvm.umax"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmUmax w)+ )+ , ("llvm.umin"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmUmin w)+ )++ , ("llvm.load.relative"+ , Poly1LLVMOverride $ \w -> SomeLLVMOverride (llvmLoadRelative w)+ )+ ]++-- | An LLVM override that is polymorphic in a single integer argument+-- (@intSz@) that is used in combination with a vector type, which can be of+-- varying sizes (@vecSz@).+newtype Poly1VecLLVMOverride p sym ext+ = Poly1VecLLVMOverride+ (forall vecSz intSz+ . (1 <= intSz)+ => NatRepr vecSz+ -> NatRepr intSz+ -> SomeLLVMOverride p sym ext)++poly1_vec_llvm_overrides ::+ IsSymInterface sym =>+ [(String, Poly1VecLLVMOverride p sym ext)]+poly1_vec_llvm_overrides =+ [ ("llvm.vector.reduce.add"+ , Poly1VecLLVMOverride $ \vecSz intSz ->+ SomeLLVMOverride (llvmVectorReduceAdd vecSz intSz)+ )+ , ("llvm.vector.reduce.mul"+ , Poly1VecLLVMOverride $ \vecSz intSz ->+ SomeLLVMOverride (llvmVectorReduceMul vecSz intSz)+ )+ , ("llvm.vector.reduce.and"+ , Poly1VecLLVMOverride $ \vecSz intSz ->+ SomeLLVMOverride (llvmVectorReduceAnd vecSz intSz)+ )+ , ("llvm.vector.reduce.or"+ , Poly1VecLLVMOverride $ \vecSz intSz ->+ SomeLLVMOverride (llvmVectorReduceOr vecSz intSz)+ )+ , ("llvm.vector.reduce.xor"+ , Poly1VecLLVMOverride $ \vecSz intSz ->+ SomeLLVMOverride (llvmVectorReduceXor vecSz intSz)+ )+ , ("llvm.vector.reduce.smax"+ , Poly1VecLLVMOverride $ \vecSz intSz ->+ SomeLLVMOverride (llvmVectorReduceSmax vecSz intSz)+ )+ , ("llvm.vector.reduce.smin"+ , Poly1VecLLVMOverride $ \vecSz intSz ->+ SomeLLVMOverride (llvmVectorReduceSmin vecSz intSz)+ )+ , ("llvm.vector.reduce.umax"+ , Poly1VecLLVMOverride $ \vecSz intSz ->+ SomeLLVMOverride (llvmVectorReduceUmax vecSz intSz)+ )+ , ("llvm.vector.reduce.umin"+ , Poly1VecLLVMOverride $ \vecSz intSz ->+ SomeLLVMOverride (llvmVectorReduceUmin vecSz intSz)+ )+ ]++------------------------------------------------------------------------+-- ** Declarations++-- | This intrinsic is currently a no-op.+--+-- We might want to support this in the future to catch undefined memory+-- accesses.+--+-- <https://llvm.org/docs/LangRef.html#llvm-lifetime-start-intrinsic LLVM docs>+llvmLifetimeStartOverride+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr) UnitType+llvmLifetimeStartOverride =+ [llvmOvr| void @llvm.lifetime.start( i64, i8* ) |]+ (\_ops _args -> return ())++-- | See comment on 'llvmLifetimeStartOverride'+--+-- <https://llvm.org/docs/LangRef.html#llvm-lifetime-end-intrinsic LLVM docs>+llvmLifetimeEndOverride+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr) UnitType+llvmLifetimeEndOverride =+ [llvmOvr| void @llvm.lifetime.end( i64, i8* ) |]+ (\_ops _args -> return ())++-- | This is a no-op.+--+-- The language reference doesn't mention the use of this intrinsic.+llvmLifetimeOverrideOverload+ :: forall width sym wptr p ext+ . ( 1 <= width, KnownNat width+ , IsSymInterface sym, HasPtrWidth wptr)+ => String -- ^ "start" or "end"+ -> NatRepr width+ -> LLVMOverride p sym ext+ (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr)+ UnitType -- It appears in practice that this is always void+llvmLifetimeOverrideOverload startOrEnd w =+ let nm = L.Symbol ("llvm.lifetime." ++ startOrEnd ++ ".p0i" ++ show (widthVal w)) in+ [llvmOvr| void $nm ( i64, #w * ) |]+ (\_ops _args -> return ())++-- | Like 'llvmLifetimeOverrideOverload', but with an opaque pointer type.+llvmLifetimeOverrideOverload_opaque+ :: forall sym wptr p ext+ . (IsSymInterface sym, HasPtrWidth wptr)+ => String -- ^ "start" or "end"+ -> LLVMOverride p sym ext+ (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr)+ UnitType -- It appears in practice that this is always void+llvmLifetimeOverrideOverload_opaque startOrEnd =+ let nm = L.Symbol ("llvm.lifetime." ++ startOrEnd ++ ".p0") in+ [llvmOvr| void $nm ( i64, ptr ) |]+ (\_ops _args -> return ())++-- | This intrinsic is currently a no-op.+--+-- We might want to support this in the future to catch undefined memory+-- writes.+--+-- <https://llvm.org/docs/LangRef.html#llvm-invariant-start-intrinsic LLVM docs>+llvmInvariantStartOverride+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => NatRepr width+ -> LLVMOverride p sym ext+ (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr)+ (LLVMPointerType wptr)+llvmInvariantStartOverride w =+ let nm = L.Symbol ("llvm.invariant.start.p0i" ++ show (widthVal w)) in+ [llvmOvr| {}* $nm ( i64, #w * ) |]+ (\_ops _args -> mkNull)++-- | Like 'llvmInvariantStartOverride', but with an opaque pointer type.+llvmInvariantStartOverride_opaque+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> BVType 64 ::> LLVMPointerType wptr)+ (LLVMPointerType wptr)+llvmInvariantStartOverride_opaque =+ let nm = L.Symbol "llvm.invariant.start.p0" in+ [llvmOvr| {}* $nm ( i64, ptr ) |]+ (\_ops _args -> mkNull)++-- | See comment on 'llvmInvariantStartOverride'.+llvmInvariantEndOverride+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => NatRepr width+ -> LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> BVType 64 ::> LLVMPointerType wptr)+ UnitType+llvmInvariantEndOverride w =+ let nm = L.Symbol ("llvm.invariant.end.p0i" ++ show (widthVal w)) in+ [llvmOvr| void $nm ( {}*, i64, #w * ) |]+ (\_ops _args -> return ())++-- | See comment on 'llvmInvariantStartOverride_opaque'.+llvmInvariantEndOverride_opaque+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> BVType 64 ::> LLVMPointerType wptr)+ UnitType+llvmInvariantEndOverride_opaque =+ let nm = L.Symbol "llvm.invariant.end.p0" in+ [llvmOvr| void $nm ( {}*, i64, ptr ) |]+ (\_ops _args -> return ())++-- | This instruction is a hint to optimizers, it isn't really useful for us.+--+-- Its runtime behavior of that of Haskell\'s 'const': just ignore the second+-- argument.+llvmExpectOverride+ :: (IsSymInterface sym, 1 <= width)+ => NatRepr width+ -> LLVMOverride p sym ext+ (EmptyCtx ::> BVType width ::> BVType width)+ (BVType width)+llvmExpectOverride w =+ let nm = L.Symbol ("llvm.expect.i" ++ show (widthVal w)) in+ [llvmOvr| #w $nm ( #w, #w ) |]+ (\_ops args ->+ Ctx.uncurryAssignment (\val _ -> pure (regValue val)) args)++-- | This intrinsic asserts that its argument is equal to 1.+--+-- We could have this generate a verification condition, but that would catch+-- clang compiler bugs (or Crucible bugs) more than user code bugs.+llvmAssumeOverride+ :: (IsSymInterface sym)+ => LLVMOverride p sym ext (EmptyCtx ::> BVType 1) UnitType+llvmAssumeOverride =+ [llvmOvr| void @llvm.assume ( i1 ) |]+ (\_ops _args -> return ())++-- | This intrinsic is sometimes inserted by clang, and we interpret it+-- as an assertion failure, similar to calling @abort()@.+llvmTrapOverride+ :: (IsSymInterface sym)+ => LLVMOverride p sym ext EmptyCtx UnitType+llvmTrapOverride =+ [llvmOvr| void @llvm.trap() |]+ (\_ops _args ->+ ovrWithBackend $ \bak ->+ liftIO $ addFailedAssertion bak $ AssertFailureSimError "llvm.trap() called" "")++-- | This is like @llvm.trap()@, but with an argument indicating which sort of+-- undefined behavior was trapped. The argument acts as an index into+-- <https://github.com/llvm/llvm-project/blob/650bbc56203c947bb85176c40ca9c7c7a91c3c57/clang/lib/CodeGen/CodeGenFunction.h#L118-L143 this list>.+-- Ideally, we would do something intelligent with this argument—see #368.+llvmUBSanTrapOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext (EmptyCtx ::> BVType 8) UnitType+llvmUBSanTrapOverride =+ [llvmOvr| void @llvm.ubsantrap( i8 ) |]+ (\_ops _args ->+ ovrWithBackend $ \bak ->+ liftIO $ addFailedAssertion bak $ AssertFailureSimError "llvm.ubsantrap() called" "")++llvmStacksave+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext EmptyCtx (LLVMPointerType wptr)+llvmStacksave =+ [llvmOvr| i8* @llvm.stacksave() |]+ (\_memOps _args -> mkNull)++llvmStackrestore+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr) UnitType+llvmStackrestore =+ [llvmOvr| void @llvm.stackrestore( i8* ) |]+ (\_memOps _args -> return ())++llvmMemmoveOverride_8_8_32+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 32 ::> BVType 32 ::> BVType 1)+ UnitType+llvmMemmoveOverride_8_8_32 =+ [llvmOvr| void @llvm.memmove.p0i8.p0i8.i32( i8*, i8*, i32, i32, i1 ) |]+ (\memOps args ->+ Ctx.uncurryAssignment (\dst src len _align v -> Libc.callMemmove memOps dst src len v) args)++llvmMemmoveOverride_8_8_32_noalign+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 32 ::> BVType 1)+ UnitType+llvmMemmoveOverride_8_8_32_noalign =+ [llvmOvr| void @llvm.memmove.p0i8.p0i8.i32( i8*, i8*, i32, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (Libc.callMemmove memOps) args)++llvmMemmoveOverride_8_8_32_noalign_opaque+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 32 ::> BVType 1)+ UnitType+llvmMemmoveOverride_8_8_32_noalign_opaque =+ [llvmOvr| void @llvm.memmove.p0.p0.i32( ptr, ptr, i32, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (Libc.callMemmove memOps) args)+++llvmMemmoveOverride_8_8_64+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 64 ::> BVType 32 ::> BVType 1)+ UnitType+llvmMemmoveOverride_8_8_64 =+ [llvmOvr| void @llvm.memmove.p0i8.p0i8.i64( i8*, i8*, i64, i32, i1 ) |]+ (\memOps args ->+ Ctx.uncurryAssignment (\dst src len _align v -> Libc.callMemmove memOps dst src len v) args)++llvmMemmoveOverride_8_8_64_noalign+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 64 ::> BVType 1)+ UnitType+llvmMemmoveOverride_8_8_64_noalign =+ [llvmOvr| void @llvm.memmove.p0i8.p0i8.i64( i8*, i8*, i64, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (Libc.callMemmove memOps) args)++llvmMemmoveOverride_8_8_64_noalign_opaque+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 64 ::> BVType 1)+ UnitType+llvmMemmoveOverride_8_8_64_noalign_opaque =+ [llvmOvr| void @llvm.memmove.p0.p0.i64( ptr, ptr, i64, i1 ) |]+ (\memOps args ->+ Ctx.uncurryAssignment (Libc.callMemmove memOps) args)+++llvmMemsetOverride_8_64+ :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> BVType 8+ ::> BVType 64+ ::> BVType 32+ ::> BVType 1)+ UnitType+llvmMemsetOverride_8_64 =+ [llvmOvr| void @llvm.memset.p0i8.i64( i8*, i8, i64, i32, i1 ) |]+ (\memOps args ->+ Ctx.uncurryAssignment (\dst val len _align v -> Libc.callMemset memOps dst val len v) args)++llvmMemsetOverride_8_64_noalign+ :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> BVType 8+ ::> BVType 64+ ::> BVType 1)+ UnitType+llvmMemsetOverride_8_64_noalign =+ [llvmOvr| void @llvm.memset.p0i8.i64( i8*, i8, i64, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (Libc.callMemset memOps) args)++llvmMemsetOverride_8_64_noalign_opaque+ :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> BVType 8+ ::> BVType 64+ ::> BVType 1)+ UnitType+llvmMemsetOverride_8_64_noalign_opaque =+ [llvmOvr| void @llvm.memset.p0.i64( ptr, i8, i64, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (Libc.callMemset memOps) args)+++llvmMemsetOverride_8_32+ :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> BVType 8+ ::> BVType 32+ ::> BVType 32+ ::> BVType 1)+ UnitType+llvmMemsetOverride_8_32 =+ [llvmOvr| void @llvm.memset.p0i8.i32( i8*, i8, i32, i32, i1 ) |]+ (\memOps args ->+ Ctx.uncurryAssignment (\dst val len _align v -> Libc.callMemset memOps dst val len v) args)++llvmMemsetOverride_8_32_noalign+ :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> BVType 8+ ::> BVType 32+ ::> BVType 1)+ UnitType+llvmMemsetOverride_8_32_noalign =+ [llvmOvr| void @llvm.memset.p0i8.i32( i8*, i8, i32, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (Libc.callMemset memOps) args)++llvmMemsetOverride_8_32_noalign_opaque+ :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> BVType 8+ ::> BVType 32+ ::> BVType 1)+ UnitType+llvmMemsetOverride_8_32_noalign_opaque =+ [llvmOvr| void @llvm.memset.p0.i32( ptr, i8, i32, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (Libc.callMemset memOps) args)+++llvmMemcpyOverride_8_8_32+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 32 ::> BVType 32 ::> BVType 1)+ UnitType+llvmMemcpyOverride_8_8_32 =+ [llvmOvr| void @llvm.memcpy.p0i8.p0i8.i32( i8*, i8*, i32, i32, i1 ) |]+ (\memOps args ->+ Ctx.uncurryAssignment (\dst src len _align v -> Libc.callMemcpy memOps dst src len v) args)++llvmMemcpyOverride_8_8_32_noalign+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 32 ::> BVType 1)+ UnitType+llvmMemcpyOverride_8_8_32_noalign =+ [llvmOvr| void @llvm.memcpy.p0i8.p0i8.i32( i8*, i8*, i32, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (Libc.callMemcpy memOps) args)++llvmMemcpyOverride_8_8_32_noalign_opaque+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 32 ::> BVType 1)+ UnitType+llvmMemcpyOverride_8_8_32_noalign_opaque =+ [llvmOvr| void @llvm.memcpy.p0.p0.i32( ptr, ptr, i32, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (Libc.callMemcpy memOps) args)+++llvmMemcpyOverride_8_8_64+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 64 ::> BVType 32 ::> BVType 1)+ UnitType+llvmMemcpyOverride_8_8_64 =+ [llvmOvr| void @llvm.memcpy.p0i8.p0i8.i64( i8*, i8*, i64, i32, i1 ) |]+ (\memOps args ->+ Ctx.uncurryAssignment (\dst src len _align v -> Libc.callMemcpy memOps dst src len v) args)++llvmMemcpyOverride_8_8_64_noalign+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 64 ::> BVType 1)+ UnitType+llvmMemcpyOverride_8_8_64_noalign =+ [llvmOvr| void @llvm.memcpy.p0i8.p0i8.i64( i8*, i8*, i64, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (Libc.callMemcpy memOps) args)++llvmMemcpyOverride_8_8_64_noalign_opaque+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr+ ::> BVType 64 ::> BVType 1)+ UnitType+llvmMemcpyOverride_8_8_64_noalign_opaque =+ [llvmOvr| void @llvm.memcpy.p0.p0.i64( ptr, ptr, i64, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (Libc.callMemcpy memOps) args)+++llvmObjectsizeOverride_32+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1) (BVType 32)+llvmObjectsizeOverride_32 =+ [llvmOvr| i32 @llvm.objectsize.i32.p0i8( i8*, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (callObjectsize memOps knownNat) args)++llvmObjectsizeOverride_32_null+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1) (BVType 32)+llvmObjectsizeOverride_32_null =+ [llvmOvr| i32 @llvm.objectsize.i32.p0i8( i8*, i1, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (callObjectsize_null memOps knownNat) args)++llvmObjectsizeOverride_32_null_dynamic+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1 ::> BVType 1) (BVType 32)+llvmObjectsizeOverride_32_null_dynamic =+ [llvmOvr| i32 @llvm.objectsize.i32.p0i8( i8*, i1, i1, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (callObjectsize_null_dynamic memOps knownNat) args)++llvmObjectsizeOverride_32_null_dynamic_opaque+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1 ::> BVType 1) (BVType 32)+llvmObjectsizeOverride_32_null_dynamic_opaque =+ [llvmOvr| i32 @llvm.objectsize.i32.p0( ptr, i1, i1, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (callObjectsize_null_dynamic memOps knownNat) args)++llvmObjectsizeOverride_64+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1) (BVType 64)+llvmObjectsizeOverride_64 =+ [llvmOvr| i64 @llvm.objectsize.i64.p0i8( i8*, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (callObjectsize memOps knownNat) args)++llvmObjectsizeOverride_64_null+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1) (BVType 64)+llvmObjectsizeOverride_64_null =+ [llvmOvr| i64 @llvm.objectsize.i64.p0i8( i8*, i1, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (callObjectsize_null memOps knownNat) args)++llvmObjectsizeOverride_64_null_dynamic+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1 ::> BVType 1) (BVType 64)+llvmObjectsizeOverride_64_null_dynamic =+ [llvmOvr| i64 @llvm.objectsize.i64.p0i8( i8*, i1, i1, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (callObjectsize_null_dynamic memOps knownNat) args)++llvmObjectsizeOverride_64_null_dynamic_opaque+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr ::> BVType 1 ::> BVType 1 ::> BVType 1) (BVType 64)+llvmObjectsizeOverride_64_null_dynamic_opaque =+ [llvmOvr| i64 @llvm.objectsize.i64.p0( ptr, i1, i1, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (callObjectsize_null_dynamic memOps knownNat) args)++-- | This instruction is a hint to code generators, which means that it is a+-- no-op for us.+--+-- <https://releases.llvm.org/12.0.0/docs/LangRef.html#llvm-prefetch-intrinsic LLVM docs>+llvmPrefetchOverride ::+ (IsSymInterface sym, HasPtrWidth wptr) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> BVType 32 ::> BVType 32 ::> BVType 32)+ UnitType+llvmPrefetchOverride =+ [llvmOvr| void @llvm.prefetch.p0i8( i8*, i32, i32, i32 ) |]+ (\_memOps _args -> pure ())++-- | Like 'llvmPrefetchOverride', but with an opaque pointer type.+llvmPrefetchOverride_opaque ::+ (IsSymInterface sym, HasPtrWidth wptr) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> BVType 32 ::> BVType 32 ::> BVType 32)+ UnitType+llvmPrefetchOverride_opaque =+ [llvmOvr| void @llvm.prefetch.p0( ptr, i32, i32, i32 ) |]+ (\_memOps _args -> pure ())++-- | This instruction is a hint to code generators, which means that it is a+-- no-op for us.+--+-- See also 'llvmPrefetchOverride'. This version exists for compatibility with+-- pre-10 versions of LLVM, where llvm.prefetch always assumed that the first+-- argument resides in address space 0.+--+-- <https://releases.llvm.org/12.0.0/docs/LangRef.html#llvm-prefetch-intrinsic LLVM docs>+llvmPrefetchOverride_preLLVM10 ::+ (IsSymInterface sym, HasPtrWidth wptr) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> BVType 32 ::> BVType 32 ::> BVType 32)+ UnitType+llvmPrefetchOverride_preLLVM10 =+ [llvmOvr| void @llvm.prefetch( i8*, i32, i32, i32 ) |]+ (\_memOps _args -> pure ())++llvmFshl ::+ (1 <= w, IsSymInterface sym) =>+ NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w ::> BVType w)+ (BVType w)+llvmFshl w =+ let nm = L.Symbol ("llvm.fshl.i" ++ show (natValue w)) in+ [llvmOvr| #w $nm ( #w, #w, #w ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callFshl w) args)++llvmFshr ::+ (1 <= w, IsSymInterface sym) =>+ NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w ::> BVType w)+ (BVType w)+llvmFshr w =+ let nm = L.Symbol ("llvm.fshr.i" ++ show (natValue w)) in+ [llvmOvr| #w $nm ( #w, #w, #w ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callFshr w) args)++llvmSaddWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w)+ (StructType (EmptyCtx ::> BVType w ::> BVType 1))+llvmSaddWithOverflow w =+ let nm = L.Symbol ("llvm.sadd.with.overflow.i" ++ show (natValue w)) in+ [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callSaddWithOverflow memOps) args)++llvmUaddWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w)+ (StructType (EmptyCtx ::> BVType w ::> BVType 1))+llvmUaddWithOverflow w =+ let nm = L.Symbol ("llvm.uadd.with.overflow.i" ++ show (natValue w)) in+ [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callUaddWithOverflow memOps) args)+++llvmSsubWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w)+ (StructType (EmptyCtx ::> BVType w ::> BVType 1))+llvmSsubWithOverflow w =+ let nm = L.Symbol ("llvm.ssub.with.overflow.i" ++ show (natValue w)) in+ [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callSsubWithOverflow memOps) args)+++llvmUsubWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w)+ (StructType (EmptyCtx ::> BVType w ::> BVType 1))+llvmUsubWithOverflow w =+ let nm = L.Symbol ("llvm.usub.with.overflow.i" ++ show (natValue w)) in+ [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callUsubWithOverflow memOps) args)++llvmSmulWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w)+ (StructType (EmptyCtx ::> BVType w ::> BVType 1))+llvmSmulWithOverflow w =+ let nm = L.Symbol ("llvm.smul.with.overflow.i" ++ show (natValue w)) in+ [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callSmulWithOverflow memOps) args)++llvmUmulWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w)+ (StructType (EmptyCtx ::> BVType w ::> BVType 1))+llvmUmulWithOverflow w =+ let nm = L.Symbol ("llvm.umul.with.overflow.i" ++ show (natValue w)) in+ [llvmOvr| { #w, i1 } $nm ( #w, #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callUmulWithOverflow memOps) args)++llvmUmax ::+ (1 <= w, IsSymInterface sym) =>+ NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w)+ (BVType w)+llvmUmax w =+ let nm = L.Symbol ("llvm.umax.i" ++ show (natValue w)) in+ [llvmOvr| #w $nm( #w, #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callUmax memOps) args)++llvmUmin ::+ (1 <= w, IsSymInterface sym) =>+ NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w)+ (BVType w)+llvmUmin w =+ let nm = L.Symbol ("llvm.umin.i" ++ show (natValue w)) in+ [llvmOvr| #w $nm( #w, #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callUmin memOps) args)++llvmSmax ::+ (1 <= w, IsSymInterface sym) =>+ NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w)+ (BVType w)+llvmSmax w =+ let nm = L.Symbol ("llvm.smax.i" ++ show (natValue w)) in+ [llvmOvr| #w $nm( #w, #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callSmax memOps) args)++llvmSmin ::+ (1 <= w, IsSymInterface sym) =>+ NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType w)+ (BVType w)+llvmSmin w =+ let nm = L.Symbol ("llvm.smin.i" ++ show (natValue w)) in+ [llvmOvr| #w $nm( #w, #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callSmin memOps) args)++llvmCtlz+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType 1)+ (BVType w)+llvmCtlz w =+ let nm = L.Symbol ("llvm.ctlz.i" ++ show (natValue w)) in+ [llvmOvr| #w $nm ( #w, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (callCtlz memOps) args)++llvmCttz+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w+ -> LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType 1)+ (BVType w)+llvmCttz w =+ let nm = L.Symbol ("llvm.cttz.i" ++ show (natValue w)) in+ [llvmOvr| #w $nm ( #w, i1 ) |]+ (\memOps args -> Ctx.uncurryAssignment (callCttz memOps) args)++llvmCtpop+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w+ -> LLVMOverride p sym ext+ (EmptyCtx ::> BVType w)+ (BVType w)+llvmCtpop w =+ let nm = L.Symbol ("llvm.ctpop.i" ++ show (natValue w)) in+ [llvmOvr| #w $nm( #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callCtpop memOps) args)++llvmBitreverse+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w+ -> LLVMOverride p sym ext+ (EmptyCtx ::> BVType w)+ (BVType w)+llvmBitreverse w =+ let nm = L.Symbol ("llvm.bitreverse.i" ++ show (natValue w)) in+ [llvmOvr| #w $nm( #w ) |]+ (\memOps args -> Ctx.uncurryAssignment (callBitreverse memOps) args)++-- | <https://llvm.org/docs/LangRef.html#llvm-bswap-intrinsics LLVM docs>+llvmBSwapOverride+ :: forall width sym p ext+ . ( 1 <= width, IsSymInterface sym)+ => NatRepr width+ -> LLVMOverride p sym ext+ (EmptyCtx ::> BVType (width * 8))+ (BVType (width * 8))+llvmBSwapOverride widthRepr =+ let width8 = natMultiply widthRepr (knownNat @8)+ nm = L.Symbol ("llvm.bswap.i" ++ show (widthVal width8))+ in+ case mulComm widthRepr (knownNat @8) of { Refl ->+ case leqMulMono (knownNat @8) widthRepr :: LeqProof width (width * 8) of { LeqProof ->+ case leqTrans (LeqProof :: LeqProof 1 width)+ (LeqProof :: LeqProof width (width * 8)) of { LeqProof ->+ -- From the LLVM docs:+ -- declare i16 @llvm.bswap.i16(i16 <id>)+ [llvmOvr| #width8 $nm( #width8 ) |]+ (\_ args -> Ctx.uncurryAssignment (Libc.callBSwap widthRepr) args)+ }}}++-- | <https://llvm.org/docs/LangRef.html#llvm-load-relative-intrinsic LLVM docs>+llvmLoadRelative ::+ ( 1 <= w+ , HasPtrWidth wptr+ , HasLLVMAnn sym+ , ?memOpts :: MemOptions+ ) =>+ NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> BVType w)+ (LLVMPointerType wptr)+llvmLoadRelative w =+ let nm = L.Symbol ("llvm.load.relative.i" ++ show (natValue w)) in+ [llvmOvr| ptr $nm( ptr, #w ) |]+ (\mvar args -> Ctx.uncurryAssignment (callLoadRelative mvar w) args)++llvmAbsOverride ::+ (1 <= w, IsSymInterface sym, HasLLVMAnn sym) =>+ NatRepr w ->+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType w ::> BVType 1)+ (BVType w)+llvmAbsOverride w =+ let nm = L.Symbol ("llvm.abs.i" ++ show (natValue w)) in+ [llvmOvr| #w $nm( #w, i1 ) |]+ (\mvar args ->+ do callStack <- callStackFromMemVar' mvar+ Ctx.uncurryAssignment (Libc.callLLVMAbs callStack w) args)++llvmCopysignOverride_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmCopysignOverride_F32 =+ [llvmOvr| float @llvm.copysign.f32( float, float ) |]+ (\_memOps args -> Ctx.uncurryAssignment callCopysign args)++llvmCopysignOverride_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmCopysignOverride_F64 =+ [llvmOvr| double @llvm.copysign.f64( double, double ) |]+ (\_memOps args -> Ctx.uncurryAssignment callCopysign args)+++llvmFabsF32+ :: forall sym p ext+ . ( IsSymInterface sym)+ => LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmFabsF32 =+ [llvmOvr| float @llvm.fabs.f32( float ) |]+ (\_memOps (Empty :> (regValue -> x)) -> do+ sym <- getSymInterface+ liftIO (iFloatAbs @_ @SingleFloat sym x))+++llvmFabsF64+ :: forall sym p ext+ . ( IsSymInterface sym)+ => LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmFabsF64 =+ [llvmOvr| double @llvm.fabs.f64( double ) |]+ (\_memOps (Empty :> (regValue -> x)) -> do+ sym <- getSymInterface+ liftIO (iFloatAbs @_ @DoubleFloat sym x))++llvmCeilOverride_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmCeilOverride_F32 =+ [llvmOvr| float @llvm.ceil.f32( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment Libc.callCeil args)++llvmCeilOverride_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmCeilOverride_F64 =+ [llvmOvr| double @llvm.ceil.f64( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment Libc.callCeil args)++llvmFloorOverride_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmFloorOverride_F32 =+ [llvmOvr| float @llvm.floor.f32( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment Libc.callFloor args)++llvmFloorOverride_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmFloorOverride_F64 =+ [llvmOvr| double @llvm.floor.f64( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment Libc.callFloor args)++llvmSqrtOverride_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmSqrtOverride_F32 =+ [llvmOvr| float @llvm.sqrt.f32( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment Libc.callSqrt args)++llvmSqrtOverride_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmSqrtOverride_F64 =+ [llvmOvr| double @llvm.sqrt.f64( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment Libc.callSqrt args)++llvmSinOverride_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmSinOverride_F32 =+ [llvmOvr| float @llvm.sin.f32( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Sin) args)++llvmSinOverride_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmSinOverride_F64 =+ [llvmOvr| double @llvm.sin.f64( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Sin) args)++llvmCosOverride_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmCosOverride_F32 =+ [llvmOvr| float @llvm.cos.f32( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Cos) args)++llvmCosOverride_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmCosOverride_F64 =+ [llvmOvr| double @llvm.cos.f64( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Cos) args)++llvmPowOverride_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmPowOverride_F32 =+ [llvmOvr| float @llvm.pow.f32( float, float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction2 W4.Pow) args)++llvmPowOverride_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmPowOverride_F64 =+ [llvmOvr| double @llvm.pow.f64( double, double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction2 W4.Pow) args)++llvmExpOverride_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmExpOverride_F32 =+ [llvmOvr| float @llvm.exp.f32( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Exp) args)++llvmExpOverride_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmExpOverride_F64 =+ [llvmOvr| double @llvm.exp.f64( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Exp) args)++llvmLogOverride_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmLogOverride_F32 =+ [llvmOvr| float @llvm.log.f32( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Log) args)++llvmLogOverride_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmLogOverride_F64 =+ [llvmOvr| double @llvm.log.f64( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Log) args)++llvmExp2Override_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmExp2Override_F32 =+ [llvmOvr| float @llvm.exp2.f32( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Exp2) args)++llvmExp2Override_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmExp2Override_F64 =+ [llvmOvr| double @llvm.exp2.f64( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Exp2) args)++llvmLog2Override_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmLog2Override_F32 =+ [llvmOvr| float @llvm.log2.f32( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Log2) args)++llvmLog2Override_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmLog2Override_F64 =+ [llvmOvr| double @llvm.log2.f64( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Log2) args)++llvmLog10Override_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmLog10Override_F32 =+ [llvmOvr| float @llvm.log10.f32( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Log10) args)++llvmLog10Override_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmLog10Override_F64 =+ [llvmOvr| double @llvm.log10.f64( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (Libc.callSpecialFunction1 W4.Log10) args)++llvmIsFpclassOverride_F32 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat+ ::> BVType 32)+ (BVType 1)+llvmIsFpclassOverride_F32 =+ [llvmOvr| i1 @llvm.is.fpclass.f32( float, i32 ) |]+ (\_memOps args -> Ctx.uncurryAssignment callIsFpclass args)++llvmIsFpclassOverride_F64 ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat+ ::> BVType 32)+ (BVType 1)+llvmIsFpclassOverride_F64 =+ [llvmOvr| i1 @llvm.is.fpclass.f64( double, i32 ) |]+ (\_memOps args -> Ctx.uncurryAssignment callIsFpclass args)++llvmFmaOverride_F32 ::+ forall sym p ext+ . IsSymInterface sym+ => LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat+ ::> FloatType SingleFloat+ ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmFmaOverride_F32 =+ [llvmOvr| float @llvm.fma.f32( float, float, float ) |]+ (\_memOps args -> Ctx.uncurryAssignment Libc.callFMA args)++llvmFmaOverride_F64 ::+ forall sym p ext+ . IsSymInterface sym+ => LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat+ ::> FloatType DoubleFloat+ ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmFmaOverride_F64 =+ [llvmOvr| double @llvm.fma.f64( double, double, double ) |]+ (\_memOps args -> Ctx.uncurryAssignment Libc.callFMA args)++llvmFmuladdOverride_F32 ::+ forall sym p ext+ . IsSymInterface sym+ => LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat+ ::> FloatType SingleFloat+ ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmFmuladdOverride_F32 =+ [llvmOvr| float @llvm.fmuladd.f32( float, float, float ) |]+ (\_memOps args -> Ctx.uncurryAssignment Libc.callFMA args)++llvmFmuladdOverride_F64 ::+ forall sym p ext+ . IsSymInterface sym+ => LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat+ ::> FloatType DoubleFloat+ ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmFmuladdOverride_F64 =+ [llvmOvr| double @llvm.fmuladd.f64( double, double, double ) |]+ (\_memOps args -> Ctx.uncurryAssignment Libc.callFMA args)+++llvmX86_pclmulqdq+--declare <2 x i64> @llvm.x86.pclmulqdq(<2 x i64>, <2 x i64>, i8) #1+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> VectorType (BVType 64)+ ::> VectorType (BVType 64)+ ::> BVType 8)+ (VectorType (BVType 64))+llvmX86_pclmulqdq =+ [llvmOvr| <2 x i64> @llvm.x86.pclmulqdq(<2 x i64>, <2 x i64>, i8) |]+ (\memOps args -> Ctx.uncurryAssignment (callX86_pclmulqdq memOps) args)+++llvmX86_SSE2_storeu_dq+ :: ( IsSymInterface sym+ , HasLLVMAnn sym+ , HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> VectorType (BVType 8))+ UnitType+llvmX86_SSE2_storeu_dq =+ [llvmOvr| void @llvm.x86.sse2.storeu.dq( i8*, <16 x i8> ) |]+ (\memOps args -> Ctx.uncurryAssignment (callStoreudq memOps) args)+++-- | Build an 'LLVMOverride' for a vector reduce intrinsic.+llvmVectorReduce ::+ (1 <= intSz)+ => String+ -- ^ The name of the operation to reduce (@add@, @mul@, etc.).+ -> (forall r args ret+ . IsSymInterface sym+ => NatRepr intSz+ -> RegEntry sym (VectorType (BVType intSz))+ -> OverrideSim p sym ext r args ret (SymBV sym intSz))+ -- ^ The semantics of the override.+ -> NatRepr vecSz+ -- ^ The size of the vector type.+ -> NatRepr intSz+ -- ^ The size of the integer type.+ -> LLVMOverride p sym ext+ (EmptyCtx ::> VectorType (BVType intSz))+ (BVType intSz)+llvmVectorReduce opName callReduce vecSz intSz =+ let nm = L.Symbol ("llvm.vector.reduce." ++ opName +++ ".v" ++ show (natValue vecSz) +++ "i" ++ show (natValue intSz)) in+ [llvmOvr| #intSz $nm( <#vecSz x #intSz> ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callReduce intSz) args)++llvmVectorReduceAdd ::+ (1 <= intSz)+ => NatRepr vecSz+ -> NatRepr intSz+ -> LLVMOverride p sym ext+ (EmptyCtx ::> VectorType (BVType intSz))+ (BVType intSz)+llvmVectorReduceAdd = llvmVectorReduce "add" callVectorReduceAdd++llvmVectorReduceMul ::+ (1 <= intSz)+ => NatRepr vecSz+ -> NatRepr intSz+ -> LLVMOverride p sym ext+ (EmptyCtx ::> VectorType (BVType intSz))+ (BVType intSz)+llvmVectorReduceMul = llvmVectorReduce "mul" callVectorReduceMul++llvmVectorReduceAnd ::+ (1 <= intSz)+ => NatRepr vecSz+ -> NatRepr intSz+ -> LLVMOverride p sym ext+ (EmptyCtx ::> VectorType (BVType intSz))+ (BVType intSz)+llvmVectorReduceAnd = llvmVectorReduce "and" callVectorReduceAnd++llvmVectorReduceOr ::+ (1 <= intSz)+ => NatRepr vecSz+ -> NatRepr intSz+ -> LLVMOverride p sym ext+ (EmptyCtx ::> VectorType (BVType intSz))+ (BVType intSz)+llvmVectorReduceOr = llvmVectorReduce "or" callVectorReduceOr++llvmVectorReduceXor ::+ (1 <= intSz)+ => NatRepr vecSz+ -> NatRepr intSz+ -> LLVMOverride p sym ext+ (EmptyCtx ::> VectorType (BVType intSz))+ (BVType intSz)+llvmVectorReduceXor = llvmVectorReduce "xor" callVectorReduceXor++llvmVectorReduceSmax ::+ (1 <= intSz)+ => NatRepr vecSz+ -> NatRepr intSz+ -> LLVMOverride p sym ext+ (EmptyCtx ::> VectorType (BVType intSz))+ (BVType intSz)+llvmVectorReduceSmax = llvmVectorReduce "smax" callVectorReduceSmax++llvmVectorReduceSmin ::+ (1 <= intSz)+ => NatRepr vecSz+ -> NatRepr intSz+ -> LLVMOverride p sym ext+ (EmptyCtx ::> VectorType (BVType intSz))+ (BVType intSz)+llvmVectorReduceSmin = llvmVectorReduce "smin" callVectorReduceSmin++llvmVectorReduceUmax ::+ (1 <= intSz)+ => NatRepr vecSz+ -> NatRepr intSz+ -> LLVMOverride p sym ext+ (EmptyCtx ::> VectorType (BVType intSz))+ (BVType intSz)+llvmVectorReduceUmax = llvmVectorReduce "umax" callVectorReduceUmax++llvmVectorReduceUmin ::+ (1 <= intSz)+ => NatRepr vecSz+ -> NatRepr intSz+ -> LLVMOverride p sym ext+ (EmptyCtx ::> VectorType (BVType intSz))+ (BVType intSz)+llvmVectorReduceUmin = llvmVectorReduce "umin" callVectorReduceUmin++------------------------------------------------------------------------+-- ** Implementations++callX86_pclmulqdq :: forall p sym ext wptr r args ret.+ (IsSymInterface sym, HasPtrWidth wptr) =>+ GlobalVar Mem ->+ RegEntry sym (VectorType (BVType 64)) ->+ RegEntry sym (VectorType (BVType 64)) ->+ RegEntry sym (BVType 8) ->+ OverrideSim p sym ext r args ret (RegValue sym (VectorType (BVType 64)))+callX86_pclmulqdq _mvar+ (regValue -> xs)+ (regValue -> ys)+ (regValue -> imm) =+ ovrWithBackend $ \bak -> do+ unless (V.length xs == 2) $+ liftIO $ addFailedAssertion bak $ AssertFailureSimError+ ("Vector length mismatch in llvm.x86.pclmulqdq intrinsic")+ (unwords ["Expected <2 x i64>, but got vector of length", show (V.length xs)])+ unless (V.length ys == 2) $+ liftIO $ addFailedAssertion bak $ AssertFailureSimError+ ("Vector length mismatch in llvm.x86.pclmulqdq intrinsic")+ (unwords ["Expected <2 x i64>, but got vector of length", show (V.length ys)])+ case BV.asUnsigned <$> asBV imm of+ Just byte ->+ do let xidx = if byte .&. 0x01 == 0 then 0 else 1+ let yidx = if byte .&. 0x10 == 0 then 0 else 1+ let sym = backendGetSym bak+ liftIO $ doPcmul sym (xs V.! xidx) (ys V.! yidx)+ _ ->+ liftIO $ addFailedAssertion bak $ AssertFailureSimError+ ("Illegal selector argument to llvm.x86.pclmulqdq")+ (unwords ["Expected concrete value but got", show (printSymExpr imm)])+ where++ doPcmul :: sym -> SymBV sym 64 -> SymBV sym 64 -> IO (V.Vector (SymBV sym 64))+ doPcmul sym x y =+ do r <- carrylessMultiply sym x y+ lo <- bvTrunc sym (knownNat @64) r+ hi <- bvSelect sym (knownNat @64) (knownNat @64) r+ -- NB, little endian because X86+ return $ V.fromList [ lo, hi ]++callStoreudq+ :: ( IsSymInterface sym+ , HasLLVMAnn sym+ , HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => GlobalVar Mem+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (VectorType (BVType 8))+ -> OverrideSim p sym ext r args ret ()+callStoreudq mvar+ (regValue -> dest)+ (regValue -> vec) =+ ovrWithBackend $ \bak -> do+ mem <- readGlobal mvar+ unless (V.length vec == 16) $+ liftIO $ addFailedAssertion bak $ AssertFailureSimError+ ("Vector length mismatch in stored_qu intrinsic.")+ (unwords ["Expected <16 x i8>, but got vector of length", show (V.length vec)])+ mem' <- liftIO $ doStore+ bak+ mem+ dest+ (VectorRepr (KnownBV @8))+ (arrayType 16 (bitvectorType (Bytes 1)))+ noAlignment+ vec+ writeGlobal mvar mem'+++-- Excerpt from the LLVM documentation:+--+-- The llvm.objectsize intrinsic is designed to provide information to+-- the optimizers to determine at compile time whether a) an operation+-- (like memcpy) will overflow a buffer that corresponds to an object,+-- or b) that a runtime check for overflow isn’t necessary. An object+-- in this context means an allocation of a specific class, structure,+-- array, or other object.+--+-- The llvm.objectsize intrinsic takes two arguments. The first+-- argument is a pointer to or into the object. The second argument is+-- a boolean and determines whether llvm.objectsize returns 0 (if+-- true) or -1 (if false) when the object size is unknown. The second+-- argument only accepts constants.+--+-- The llvm.objectsize intrinsic is lowered to a constant representing+-- the size of the object concerned. If the size cannot be determined+-- at compile time, llvm.objectsize returns i32/i64 -1 or 0 (depending+-- on the min argument).+callObjectsize+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> NatRepr w+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (BVType 1)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callObjectsize _mvar w+ (regValue -> _ptr)+ (regValue -> flag) = do+ sym <- getSymInterface+ liftIO $ do+ -- Ignore the pointer value, and just return the value for unknown, as+ -- defined by the documenatation. If an `objectsize` invocation survives+ -- through compilation for us to see, that means the compiler could not+ -- determine the value.+ t <- bvIsNonzero sym flag+ z <- bvZero sym w+ n <- bvNotBits sym z -- NB: -1 is the boolean negation of zero+ bvIte sym t z n++callObjectsize_null+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> NatRepr w+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (BVType 1)+ -> RegEntry sym (BVType 1)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callObjectsize_null mvar w ptr flag _nullUnknown = callObjectsize mvar w ptr flag++callObjectsize_null_dynamic+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> NatRepr w+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (BVType 1)+ -> RegEntry sym (BVType 1)+ -> RegEntry sym (BVType 1)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callObjectsize_null_dynamic mvar w ptr flag _nullUnknown (regValue -> dynamic) =+ ovrWithBackend $ \bak -> do+ let sym = backendGetSym bak+ liftIO $+ do notDynamic <- notPred sym =<< bvIsNonzero sym dynamic+ assert bak notDynamic (AssertFailureSimError "llvm.objectsize called with `dynamic` set to `true`" "")+ callObjectsize mvar w ptr flag++callCtlz+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType 1)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callCtlz _mvar+ (regValue -> val)+ (regValue -> isZeroUndef) =+ ovrWithBackend $ \bak -> do+ sym <- getSymInterface+ liftIO $ do+ isNonzero <- bvIsNonzero sym val+ zeroOK <- notPred sym =<< bvIsNonzero sym isZeroUndef+ p <- orPred sym isNonzero zeroOK+ assert bak p (AssertFailureSimError "Ctlz called with disallowed zero value" "")+ bvCountLeadingZeros sym val++callFshl+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callFshl w x y amt =+ ovrWithBackend $ \bak -> liftIO $ do+ let sym = backendGetSym bak+ LeqProof <- return (dblPosIsPos (leqProof (knownNat @1) w))+ Just LeqProof <- return (testLeq (addNat w (knownNat @1)) (addNat w w))++ -- concatenate the values together+ xy <- bvConcat sym (regValue x) (regValue y)++ -- The shift argument is treated as an unsigned amount modulo the element size of the arguments.+ m <- bvLit sym w (BV.width w)+ mamt <- bvUrem sym (regValue amt) m+ mamt' <- bvZext sym (addNat w w) mamt++ -- shift left, select high bits+ z <- bvShl sym xy mamt'+ bvSelect sym w w z++callFshr+ :: (1 <= w, IsSymInterface sym)+ => NatRepr w+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callFshr w x y amt =+ ovrWithBackend $ \bak -> liftIO $ do+ LeqProof <- return (dblPosIsPos (leqProof (knownNat @1) w))+ LeqProof <- return (addPrefixIsLeq w w)+ Just LeqProof <- return (testLeq (addNat w (knownNat @1)) (addNat w w))+ let sym = backendGetSym bak++ -- concatenate the values together+ xy <- bvConcat sym (regValue x) (regValue y)++ -- The shift argument is treated as an unsigned amount modulo the element size of the arguments.+ m <- bvLit sym w (BV.width w)+ mamt <- bvUrem sym (regValue amt) m+ mamt' <- bvZext sym (addNat w w) mamt++ -- shift right, select low bits+ z <- bvLshr sym xy mamt'+ bvSelect sym (knownNat @0) w z++callSaddWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))+callSaddWithOverflow _mvar+ (regValue -> x)+ (regValue -> y) =+ ovrWithBackend $ \bak -> liftIO $ do+ let sym = backendGetSym bak+ (ov, z) <- addSignedOF sym x y+ ov' <- predToBV sym ov (knownNat @1)+ return (Empty :> RV z :> RV ov')++callUaddWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))+callUaddWithOverflow _mvar+ (regValue -> x)+ (regValue -> y) = do+ sym <- getSymInterface+ liftIO $ do+ (ov, z) <- addUnsignedOF sym x y+ ov' <- predToBV sym ov (knownNat @1)+ return (Empty :> RV z :> RV ov')++callUsubWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))+callUsubWithOverflow _mvar+ (regValue -> x)+ (regValue -> y) = do+ sym <- getSymInterface+ liftIO $ do+ (ov, z) <- subUnsignedOF sym x y+ ov' <- predToBV sym ov (knownNat @1)+ return (Empty :> RV z :> RV ov')++callSsubWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))+callSsubWithOverflow _mvar+ (regValue -> x)+ (regValue -> y) = do+ sym <- getSymInterface+ liftIO $ do+ (ov, z) <- subSignedOF sym x y+ ov' <- predToBV sym ov (knownNat @1)+ return (Empty :> RV z :> RV ov')++callSmulWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))+callSmulWithOverflow _mvar+ (regValue -> x)+ (regValue -> y) = do+ sym <- getSymInterface+ liftIO $ do+ (ov, z) <- mulSignedOF sym x y+ ov' <- predToBV sym ov (knownNat @1)+ return (Empty :> RV z :> RV ov')++callUmulWithOverflow+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (StructType (EmptyCtx ::> BVType w ::> BVType 1)))+callUmulWithOverflow _mvar+ (regValue -> x)+ (regValue -> y) = do+ sym <- getSymInterface+ liftIO $ do+ (ov, z) <- mulUnsignedOF sym x y+ ov' <- predToBV sym ov (knownNat @1)+ return (Empty :> RV z :> RV ov')++callUmax+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callUmax _mvar (regValue -> x) (regValue -> y) = do+ sym <- getSymInterface+ liftIO $ bvUmax sym x y++-- | Compute the unsigned maximum of two bitvectors.+bvUmax ::+ (IsExprBuilder sym, 1 <= w)+ => sym+ -> SymBV sym w+ -> SymBV sym w+ -> IO (SymBV sym w)+bvUmax sym x y = do+ xGtY <- bvUgt sym x y+ bvIte sym xGtY x y++callUmin+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callUmin _mvar (regValue -> x) (regValue -> y) = do+ sym <- getSymInterface+ liftIO $ bvUmin sym x y++-- | Compute the unsigned minimum of two bitvectors.+bvUmin ::+ (IsExprBuilder sym, 1 <= w)+ => sym+ -> SymBV sym w+ -> SymBV sym w+ -> IO (SymBV sym w)+bvUmin sym x y = do+ xLtY <- bvUlt sym x y+ bvIte sym xLtY x y++callSmax+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callSmax _mvar (regValue -> x) (regValue -> y) = do+ sym <- getSymInterface+ liftIO $ bvSmax sym x y++-- | Compute the signed maximum of two bitvectors.+bvSmax ::+ (IsExprBuilder sym, 1 <= w)+ => sym+ -> SymBV sym w+ -> SymBV sym w+ -> IO (SymBV sym w)+bvSmax sym x y = do+ xGtY <- bvSgt sym x y+ bvIte sym xGtY x y++callSmin+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callSmin _mvar (regValue -> x) (regValue -> y) = do+ sym <- getSymInterface+ liftIO $ bvSmin sym x y++-- | Compute the signed minimum of two bitvectors.+bvSmin ::+ (IsExprBuilder sym, 1 <= w)+ => sym+ -> SymBV sym w+ -> SymBV sym w+ -> IO (SymBV sym w)+bvSmin sym x y = do+ xLtY <- bvSlt sym x y+ bvIte sym xLtY x y+++callCttz+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType 1)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callCttz _mvar+ (regValue -> val)+ (regValue -> isZeroUndef) =+ ovrWithBackend $ \bak -> do+ let sym = backendGetSym bak+ liftIO $ do+ isNonzero <- bvIsNonzero sym val+ zeroOK <- notPred sym =<< bvIsNonzero sym isZeroUndef+ p <- orPred sym isNonzero zeroOK+ assert bak p (AssertFailureSimError "Cttz called with disallowed zero value" "")+ bvCountTrailingZeros sym val++callCtpop+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callCtpop _mvar+ (regValue -> val) = do+ sym <- getSymInterface+ liftIO $ bvPopcount sym val++callBitreverse+ :: (1 <= w, IsSymInterface sym)+ => GlobalVar Mem+ -> RegEntry sym (BVType w)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callBitreverse _mvar+ (regValue -> val) = do+ sym <- getSymInterface+ liftIO $ bvBitreverse sym val++-- | Strictly speaking, this doesn't quite conform to the C99 description of+-- @copysign@, since @copysign(NaN, -1.0)@ should return @NaN@ with a negative+-- sign bit. @libBF@ does not provide a way to distinguish between @NaN@ values+-- with different sign bits, however, so @copysign@ will always turn a @NaN@+-- argument into a positive, \"quiet\" @NaN@.+callCopysign ::+ forall fi p sym ext r args ret.+ IsSymInterface sym =>+ RegEntry sym (FloatType fi) ->+ RegEntry sym (FloatType fi) ->+ OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))+callCopysign+ (regValue -> x)+ (regValue -> y) = do+ sym <- getSymInterface+ liftIO $ do+ xIsNeg <- iFloatIsNeg @_ @fi sym x+ yIsNeg <- iFloatIsNeg @_ @fi sym y+ signsSame <- eqPred sym xIsNeg yIsNeg+ xNegated <- iFloatNeg @_ @fi sym x+ iFloatIte @_ @fi sym signsSame x xNegated++-- | An implementation of the @llvm.is.fpclass@ intrinsic. This essentially+-- combines several different floating-point checks (checking for @NaN@,+-- infinity, zero, etc.) into a single function. The second argument is a+-- bitmask that controls which properties to check of the first argument.+-- The different checks in the bitmask are described by the table here:+-- <https://llvm.org/docs/LangRef.html#id1566>+--+-- The specification requires being able to distinguish between signaling+-- @NaN@s (bit 0 of the bitmask) and quit @NaN@s (bit 1 of the bitmask), but+-- @crucible-llvm@ does not have the ability to do this. As a result, both+-- @NaN@ checks will always return true in this implementation, regardless of+-- whether they are signaling or quiet @NaN@s.+callIsFpclass ::+ forall fi p sym ext r args ret.+ IsSymInterface sym =>+ RegEntry sym (FloatType fi) ->+ RegEntry sym (BVType 32) ->+ OverrideSim p sym ext r args ret (RegValue sym (BVType 1))+callIsFpclass regOp@(regValue -> op) (regValue -> test) = do+ sym <- getSymInterface+ let w1 = knownNat @1+ bv1 <- liftIO $ bvZero sym w1+ bv0 <- liftIO $ bvOne sym w1++ let negative bit = liftIO $ do+ isNeg <- iFloatIsNeg @_ @fi sym op+ liftIO $ bvIte sym isNeg bit bv0++ let positive bit = liftIO $ do+ isPos <- iFloatIsPos @_ @fi sym op+ liftIO $ bvIte sym isPos bit bv0++ let negAndPos doCheck = liftIO $ do+ check <- doCheck+ checkN <- negative check+ checkP <- positive check+ pure (checkN, checkP)++ let callIsInf x = do+ isInf <- iFloatIsInf @_ @fi sym x+ bvIte sym isInf bv1 bv0++ let callIsNormal x = do+ isNorm <- iFloatIsNorm @_ @fi sym x+ bvIte sym isNorm bv1 bv0++ let callIsSubnormal x = do+ isSubnorm <- iFloatIsSubnorm @_ @fi sym x+ bvIte sym isSubnorm bv1 bv0++ let callIsZero x = do+ is0 <- iFloatIsZero @_ @fi sym x+ bvIte sym is0 bv1 bv0++ isNan <- Libc.callIsnan w1 regOp+ (isInfN, isInfP) <- negAndPos $ callIsInf op+ (isNormN, isNormP) <- negAndPos $ callIsNormal op+ (isSubnormN, isSubnormP) <- negAndPos $ callIsSubnormal op+ (isZeroN, isZeroP) <- negAndPos $ callIsZero op++ foldM+ (\bits (bitNum, check) -> liftIO $ do+ isBitSet <- liftIO $ testBitBV sym bitNum test+ newBit <- liftIO $ bvIte sym isBitSet check bv0+ liftIO $ bvOrBits sym newBit bits)+ bv0+ [ (0, isNan) -- Signaling NaN+ , (1, isNan) -- Quiet NaN+ , (2, isInfN) -- Negative infinity+ , (3, isNormN) -- Negative normal+ , (4, isSubnormN) -- Negative subnormal+ , (5, isZeroN) -- Negative zero+ , (6, isZeroP) -- Positive zero+ , (7, isSubnormP) -- Positive subnormal+ , (8, isNormP) -- Positive normal+ , (9, isInfP) -- Positive infinity+ ]++-- | An override for the @llvm.load.relative.i*@ family of intrinsics. Broadly+-- speaking, this loads a pointer at from the first argument (a pointer to an+-- array) at the value of the second argument (the offset). However, due to the+-- reasons described in+-- @Note [Undoing LLVM's relative table lookup conversion pass]@ in+-- "Lang.Crucible.LLVM.Globals", this override adjusts the offset before+-- performing the load.+callLoadRelative ::+ ( 1 <= w+ , IsSymInterface sym+ , HasPtrWidth wptr+ , HasLLVMAnn sym+ , ?memOpts :: MemOptions+ ) =>+ GlobalVar Mem ->+ NatRepr w ->+ RegEntry sym (LLVMPointerType wptr) ->+ RegEntry sym (BVType w) ->+ OverrideSim p sym ext r args ret (LLVMPtr sym wptr)+callLoadRelative mvar w (regValue -> ptr) (regValue -> offsetInWords32) = do+ mem <- readGlobal mvar+ ovrWithBackend $ \bak -> liftIO $ do+ let sym = backendGetSym bak+ -- We cannot use the original offset value as-is because LLVM assumes that+ -- it is loading an i32 value, but we have altered the first argument to+ -- point to an array of i8*s instead, which may have different sizes. As+ -- such, we adjust the offset value by (1) dividing it by 4 (the size of an+ -- i32 value in bytes), and (2) multiplying it by the size of an i8*.+ bvFour <- bvLit sym w $ BV.mkBV w 4+ offsetInElems <- bvUdiv sym offsetInWords32 bvFour+ ptrWidthBytes <-+ bvLit sym w $+ BV.uquot+ (BV.mkBV w (intValue ?ptrWidth))+ (BV.mkBV w 8)+ offsetInWordsPtrWidth <-+ bvMul sym offsetInElems ptrWidthBytes+ -- There is no guarantee that `wptr` is the same size as `w`, so we+ -- sign-extend or truncate the offset (of size `w`) as needed to make it be+ -- of size `wptr`.+ offsetInWordsPtrWidth' <-+ sextendBVTo sym w ?ptrWidth offsetInWordsPtrWidth+ ptr' <- ptrAdd sym ?ptrWidth ptr offsetInWordsPtrWidth'+ let ty = bitvectorType (bitsToBytes (natValue ?ptrWidth))+ doLoad bak mem ptr' ty PtrRepr noAlignment++-- | The semantics of an LLVM vector reduce intrinsic.+callVectorReduce ::+ -- | The operation which performs the reduction (e.g., addition,+ -- multiplication, etc.)+ (RegValue sym tp -> RegValue sym tp -> IO (RegValue sym tp)) ->+ -- | The identity element for the reduction operation. (For addition,+ -- this is @0@; for multiplication, this is @1@, and so on.)+ RegValue sym tp ->+ -- | The vector to reduce.+ RegEntry sym (VectorType tp) ->+ OverrideSim p sym ext r args ret (RegValue sym tp)+callVectorReduce reduceOp identityVal (regValue -> vec) =+ liftIO $ V.foldM reduceOp identityVal vec++callVectorReduceAdd ::+ (IsSymInterface sym, 1 <= intSz) =>+ NatRepr intSz ->+ RegEntry sym (VectorType (BVType intSz)) ->+ OverrideSim p sym ext r args ret (SymBV sym intSz)+callVectorReduceAdd intSz vec = do+ sym <- getSymInterface+ zero <- liftIO $ bvZero sym intSz+ callVectorReduce (bvAdd sym) zero vec++callVectorReduceMul ::+ (IsSymInterface sym, 1 <= intSz) =>+ NatRepr intSz ->+ RegEntry sym (VectorType (BVType intSz)) ->+ OverrideSim p sym ext r args ret (SymBV sym intSz)+callVectorReduceMul intSz vec = do+ sym <- getSymInterface+ one <- liftIO $ bvOne sym intSz+ callVectorReduce (bvMul sym) one vec++callVectorReduceAnd ::+ (IsSymInterface sym, 1 <= intSz) =>+ NatRepr intSz ->+ RegEntry sym (VectorType (BVType intSz)) ->+ OverrideSim p sym ext r args ret (SymBV sym intSz)+callVectorReduceAnd intSz vec = do+ sym <- getSymInterface+ zero <- liftIO $ bvZero sym intSz+ ones <- liftIO $ bvNotBits sym zero+ callVectorReduce (bvAndBits sym) ones vec++callVectorReduceOr ::+ (IsSymInterface sym, 1 <= intSz) =>+ NatRepr intSz ->+ RegEntry sym (VectorType (BVType intSz)) ->+ OverrideSim p sym ext r args ret (SymBV sym intSz)+callVectorReduceOr intSz vec = do+ sym <- getSymInterface+ zero <- liftIO $ bvZero sym intSz+ callVectorReduce (bvOrBits sym) zero vec++callVectorReduceXor ::+ (IsSymInterface sym, 1 <= intSz) =>+ NatRepr intSz ->+ RegEntry sym (VectorType (BVType intSz)) ->+ OverrideSim p sym ext r args ret (SymBV sym intSz)+callVectorReduceXor intSz vec = do+ sym <- getSymInterface+ zero <- liftIO $ bvZero sym intSz+ callVectorReduce (bvXorBits sym) zero vec++callVectorReduceSmax ::+ (IsSymInterface sym, 1 <= intSz) =>+ NatRepr intSz ->+ RegEntry sym (VectorType (BVType intSz)) ->+ OverrideSim p sym ext r args ret (SymBV sym intSz)+callVectorReduceSmax intSz vec = do+ sym <- getSymInterface+ smin <- liftIO $ minSignedBV sym intSz+ callVectorReduce (bvSmax sym) smin vec++callVectorReduceSmin ::+ (IsSymInterface sym, 1 <= intSz) =>+ NatRepr intSz ->+ RegEntry sym (VectorType (BVType intSz)) ->+ OverrideSim p sym ext r args ret (SymBV sym intSz)+callVectorReduceSmin intSz vec = do+ sym <- getSymInterface+ smax <- liftIO $ maxSignedBV sym intSz+ callVectorReduce (bvSmin sym) smax vec++callVectorReduceUmax ::+ (IsSymInterface sym, 1 <= intSz) =>+ NatRepr intSz ->+ RegEntry sym (VectorType (BVType intSz)) ->+ OverrideSim p sym ext r args ret (SymBV sym intSz)+callVectorReduceUmax intSz vec = do+ sym <- getSymInterface+ umin <- liftIO $ minUnsignedBV sym intSz+ callVectorReduce (bvUmax sym) umin vec++callVectorReduceUmin ::+ (IsSymInterface sym, 1 <= intSz) =>+ NatRepr intSz ->+ RegEntry sym (VectorType (BVType intSz)) ->+ OverrideSim p sym ext r args ret (SymBV sym intSz)+callVectorReduceUmin intSz vec = do+ sym <- getSymInterface+ umax <- liftIO $ maxUnsignedBV sym intSz+ callVectorReduce (bvUmin sym) umax vec
src/Lang/Crucible/LLVM/Intrinsics/Libc.hs view
@@ -43,1659 +43,1800 @@ import qualified Data.Parameterized.Context as Ctx import What4.Interface-import What4.InterpretedFloatingPoint (IsInterpretedFloatExprBuilder(..))-import What4.ProgramLoc (plSourceLoc)-import qualified What4.SpecialFunctions as W4--import Lang.Crucible.Backend-import Lang.Crucible.CFG.Common-import Lang.Crucible.Types-import Lang.Crucible.Simulator.ExecutionTree-import Lang.Crucible.Simulator.OverrideSim-import Lang.Crucible.Simulator.RegMap-import Lang.Crucible.Simulator.SimError--import Lang.Crucible.LLVM.Bytes-import Lang.Crucible.LLVM.DataLayout-import qualified Lang.Crucible.LLVM.Errors.Poison as Poison-import qualified Lang.Crucible.LLVM.Errors.UndefinedBehavior as UB-import Lang.Crucible.LLVM.MalformedLLVMModule-import Lang.Crucible.LLVM.MemModel-import Lang.Crucible.LLVM.MemModel.CallStack (CallStack)-import qualified Lang.Crucible.LLVM.MemModel.Type as G-import qualified Lang.Crucible.LLVM.MemModel.Generic as G-import Lang.Crucible.LLVM.MemModel.Partial-import Lang.Crucible.LLVM.Printf-import Lang.Crucible.LLVM.QQ( llvmOvr )-import Lang.Crucible.LLVM.TypeContext--import Lang.Crucible.LLVM.Intrinsics.Common-import Lang.Crucible.LLVM.Intrinsics.Options----------------------------------------------------------------------------- ** Declarations---llvmMemcpyOverride- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> LLVMPointerType wptr- ::> BVType wptr)- (LLVMPointerType wptr)-llvmMemcpyOverride =- [llvmOvr| i8* @memcpy( i8*, i8*, size_t ) |]- (\memOps bak args ->- do volatile <- liftIO $ RegEntry knownRepr <$> bvLit (backendGetSym bak) knownNat (BV.zero knownNat)- Ctx.uncurryAssignment (callMemcpy bak memOps)- (args :> volatile)- return $ regValue $ args^._1 -- return first argument- )---llvmMemcpyChkOverride- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> LLVMPointerType wptr- ::> BVType wptr- ::> BVType wptr)- (LLVMPointerType wptr)-llvmMemcpyChkOverride =- [llvmOvr| i8* @__memcpy_chk ( i8*, i8*, size_t, size_t ) |]- (\memOps bak args ->- do let args' = Empty :> (args^._1) :> (args^._2) :> (args^._3)- volatile <- liftIO $ RegEntry knownRepr <$> bvLit (backendGetSym bak) knownNat (BV.zero knownNat)- Ctx.uncurryAssignment (callMemcpy bak memOps)- (args' :> volatile)- return $ regValue $ args^._1 -- return first argument- )--llvmMemmoveOverride- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> (LLVMPointerType wptr)- ::> (LLVMPointerType wptr)- ::> BVType wptr)- (LLVMPointerType wptr)-llvmMemmoveOverride =- [llvmOvr| i8* @memmove( i8*, i8*, size_t ) |]- (\memOps bak args ->- do volatile <- liftIO (RegEntry knownRepr <$> bvLit (backendGetSym bak) knownNat (BV.zero knownNat))- Ctx.uncurryAssignment (callMemmove bak memOps)- (args :> volatile)- return $ regValue $ args^._1 -- return first argument- )--llvmMemsetOverride :: forall p sym wptr.- (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> BVType 32- ::> BVType wptr)- (LLVMPointerType wptr)-llvmMemsetOverride =- [llvmOvr| i8* @memset( i8*, i32, size_t ) |]- (\memOps bak args ->- do let sym = backendGetSym bak- LeqProof <- return (leqTrans @9 @16 @wptr LeqProof LeqProof)- let dest = args^._1- val <- liftIO (RegEntry knownRepr <$> bvTrunc sym (knownNat @8) (regValue (args^._2)))- let len = args^._3- volatile <- liftIO- (RegEntry knownRepr <$> bvLit sym knownNat (BV.zero knownNat))- callMemset bak memOps dest val len volatile- return (regValue dest)- )--llvmMemsetChkOverride- :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> BVType 32- ::> BVType wptr- ::> BVType wptr)- (LLVMPointerType wptr)-llvmMemsetChkOverride =- [llvmOvr| i8* @__memset_chk( i8*, i32, size_t, size_t ) |]- (\memOps bak args ->- do let sym = backendGetSym bak- let dest = args^._1- val <- liftIO- (RegEntry knownRepr <$> bvTrunc sym knownNat (regValue (args^._2)))- let len = args^._3- volatile <- liftIO- (RegEntry knownRepr <$> bvLit sym knownNat (BV.zero knownNat))- callMemset bak memOps dest val len volatile- return (regValue dest)- )----------------------------------------------------------------------------- *** Allocation--llvmCallocOverride- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?lc :: TypeContext, ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> BVType wptr ::> BVType wptr)- (LLVMPointerType wptr)-llvmCallocOverride =- let alignment = maxAlignment (llvmDataLayout ?lc) in- [llvmOvr| i8* @calloc( size_t, size_t ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callCalloc bak memOps alignment) args)---llvmReallocOverride- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?lc :: TypeContext, ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> BVType wptr)- (LLVMPointerType wptr)-llvmReallocOverride =- let alignment = maxAlignment (llvmDataLayout ?lc) in- [llvmOvr| i8* @realloc( i8*, size_t ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callRealloc bak memOps alignment) args)--llvmMallocOverride- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?lc :: TypeContext, ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> BVType wptr)- (LLVMPointerType wptr)-llvmMallocOverride =- let alignment = maxAlignment (llvmDataLayout ?lc) in- [llvmOvr| i8* @malloc( size_t ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callMalloc bak memOps alignment) args)--posixMemalignOverride ::- ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?lc :: TypeContext, ?memOpts :: MemOptions ) =>- LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> BVType wptr- ::> BVType wptr)- (BVType 32)-posixMemalignOverride =- [llvmOvr| i32 @posix_memalign( i8**, size_t, size_t ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callPosixMemalign bak memOps) args)---llvmFreeOverride- :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr)- UnitType-llvmFreeOverride =- [llvmOvr| void @free( i8* ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callFree bak memOps) args)----------------------------------------------------------------------------- *** Strings and I/O--llvmPrintfOverride- :: ( IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> VectorType AnyType)- (BVType 32)-llvmPrintfOverride =- [llvmOvr| i32 @printf( i8*, ... ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callPrintf bak memOps) args)--llvmPrintfChkOverride- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> BVType 32- ::> LLVMPointerType wptr- ::> VectorType AnyType)- (BVType 32)-llvmPrintfChkOverride =- [llvmOvr| i32 @__printf_chk( i32, i8*, ... ) |]- (\memOps bak args -> Ctx.uncurryAssignment (\_flg -> callPrintf bak memOps) args)---llvmPutCharOverride- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym (EmptyCtx ::> BVType 32) (BVType 32)-llvmPutCharOverride =- [llvmOvr| i32 @putchar( i32 ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callPutChar bak memOps) args)---llvmPutsOverride- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr) (BVType 32)-llvmPutsOverride =- [llvmOvr| i32 @puts( i8* ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callPuts bak memOps) args)--llvmStrlenOverride- :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => LLVMOverride p sym (EmptyCtx ::> LLVMPointerType wptr) (BVType wptr)-llvmStrlenOverride =- [llvmOvr| size_t @strlen( i8* ) |]- (\memOps bak args -> Ctx.uncurryAssignment (callStrlen bak memOps) args)----------------------------------------------------------------------------- ** Implementations----------------------------------------------------------------------------- *** Allocation--callRealloc- :: ( IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym- , ?memOpts :: MemOptions )- => bak- -> GlobalVar Mem- -> Alignment- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (BVType wptr)- -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))-callRealloc bak mvar alignment (regValue -> ptr) (regValue -> sz) =- do let sym = backendGetSym bak- szZero <- liftIO (notPred sym =<< bvIsNonzero sym sz)- ptrNull <- liftIO (ptrIsNull sym PtrWidth ptr)- loc <- liftIO (plSourceLoc <$> getCurrentProgramLoc sym)- let displayString = "<realloc> " ++ show loc-- symbolicBranches emptyRegMap- -- If the pointer is null, behave like malloc- [ ( ptrNull- , modifyGlobal mvar $ \mem -> liftIO $ doMalloc bak G.HeapAlloc G.Mutable displayString mem sz alignment- , Nothing- )-- -- If the size is zero, behave like malloc (of zero bytes) then free- , (szZero- , modifyGlobal mvar $ \mem -> liftIO $- do (newp, mem1) <- doMalloc bak G.HeapAlloc G.Mutable displayString mem sz alignment- mem2 <- doFree bak mem1 ptr- return (newp, mem2)- , Nothing- )-- -- Otherwise, allocate a new region, memcopy `sz` bytes and free the old pointer- , (truePred sym- , modifyGlobal mvar $ \mem -> liftIO $- do (newp, mem1) <- doMalloc bak G.HeapAlloc G.Mutable displayString mem sz alignment- mem2 <- uncheckedMemcpy sym mem1 newp ptr sz- mem3 <- doFree bak mem2 ptr- return (newp, mem3)- , Nothing)- ]---callPosixMemalign- :: ( IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr- , ?lc :: TypeContext, ?memOpts :: MemOptions )- => bak- -> GlobalVar Mem- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (BVType wptr)- -> RegEntry sym (BVType wptr)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))-callPosixMemalign bak mvar (regValue -> outPtr) (regValue -> align) (regValue -> sz) =- let sym = backendGetSym bak in- case asBV align of- Nothing -> fail $ unwords ["posix_memalign: alignment value must be concrete:", show (printSymExpr align)]- Just concrete_align ->- case toAlignment (toBytes (BV.asUnsigned concrete_align)) of- Nothing -> fail $ unwords ["posix_memalign: invalid alignment value:", show concrete_align]- Just a ->- let dl = llvmDataLayout ?lc in- modifyGlobal mvar $ \mem -> liftIO $- do loc <- plSourceLoc <$> getCurrentProgramLoc sym- let displayString = "<posix_memaign> " ++ show loc- (p, mem') <- doMalloc bak G.HeapAlloc G.Mutable displayString mem sz a- mem'' <- storeRaw bak mem' outPtr (bitvectorType (dl^.ptrSize)) (dl^.ptrAlign) (ptrToPtrVal p)- z <- bvLit sym knownNat (BV.zero knownNat)- return (z, mem'')--callMalloc- :: ( IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => bak- -> GlobalVar Mem- -> Alignment- -> RegEntry sym (BVType wptr)- -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))-callMalloc bak mvar alignment (regValue -> sz) =- modifyGlobal mvar $ \mem -> liftIO $- do loc <- plSourceLoc <$> getCurrentProgramLoc (backendGetSym bak)- let displayString = "<malloc> " ++ show loc- doMalloc bak G.HeapAlloc G.Mutable displayString mem sz alignment--callCalloc- :: ( IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => bak- -> GlobalVar Mem- -> Alignment- -> RegEntry sym (BVType wptr)- -> RegEntry sym (BVType wptr)- -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))-callCalloc bak mvar alignment- (regValue -> sz)- (regValue -> num) =- modifyGlobal mvar $ \mem -> liftIO $- doCalloc bak mem sz num alignment--callFree- :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr)- => bak- -> GlobalVar Mem- -> RegEntry sym (LLVMPointerType wptr)- -> OverrideSim p sym ext r args ret ()-callFree bak mvar- (regValue -> ptr) =- modifyGlobal mvar $ \mem -> liftIO $- do mem' <- doFree bak mem ptr- return ((), mem')----------------------------------------------------------------------------- *** Memory manipulation--callMemcpy- :: ( IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => bak- -> GlobalVar Mem- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType 1)- -> OverrideSim p sym ext r args ret ()-callMemcpy bak mvar- (regValue -> dest)- (regValue -> src)- (RegEntry (BVRepr w) len)- _volatile =- modifyGlobal mvar $ \mem -> liftIO $- do mem' <- doMemcpy bak w mem True dest src len- return ((), mem')---- NB the only difference between memcpy and memove--- is that memmove does not assert that the memory--- ranges are disjoint. The underlying operation--- works correctly in both cases.-callMemmove- :: ( IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => bak- -> GlobalVar Mem- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType 1)- -> OverrideSim p sym ext r args ret ()-callMemmove bak mvar- (regValue -> dest)- (regValue -> src)- (RegEntry (BVRepr w) len)- _volatile =- -- FIXME? add assertions about alignment- modifyGlobal mvar $ \mem -> liftIO $- do mem' <- doMemcpy bak w mem False dest src len- return ((), mem')--callMemset- :: (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr)- => bak- -> GlobalVar Mem- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (BVType 8)- -> RegEntry sym (BVType w)- -> RegEntry sym (BVType 1)- -> OverrideSim p sym ext r args ret ()-callMemset bak mvar- (regValue -> dest)- (regValue -> val)- (RegEntry (BVRepr w) len)- _volatile =- modifyGlobal mvar $ \mem -> liftIO $- do mem' <- doMemset bak w mem dest val len- return ((), mem')----------------------------------------------------------------------------- *** Strings and I/O--callPutChar- :: (IsSymBackend sym bak)- => bak- -> GlobalVar Mem- -> RegEntry sym (BVType 32)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))-callPutChar _bak _mvar- (regValue -> ch) = do- h <- printHandle <$> getContext- let chval = maybe '?' (toEnum . fromInteger) (BV.asUnsigned <$> asBV ch)- liftIO $ hPutChar h chval- return ch--callPuts- :: ( IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym- , ?memOpts :: MemOptions )- => bak- -> GlobalVar Mem- -> RegEntry sym (LLVMPointerType wptr)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))-callPuts bak mvar- (regValue -> strPtr) = do- mem <- readGlobal mvar- str <- liftIO $ loadString bak mem strPtr Nothing- h <- printHandle <$> getContext- liftIO $ hPutStrLn h (UTF8.toString str)- -- return non-negative value on success- liftIO $ bvLit (backendGetSym bak) knownNat (BV.one knownNat)--callStrlen- :: ( IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym- , ?memOpts :: MemOptions )- => bak- -> GlobalVar Mem- -> RegEntry sym (LLVMPointerType wptr)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType wptr))-callStrlen bak mvar (regValue -> strPtr) = do- mem <- readGlobal mvar- liftIO $ strLen bak mem strPtr--callAssert- :: ( IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym- , ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions )- => Bool -- ^ 'True' if this is @__assert_fail()@, 'False' otherwise.- -> GlobalVar Mem- -> bak- -> Ctx.Assignment (RegEntry sym)- (EmptyCtx ::> LLVMPointerType wptr- ::> LLVMPointerType wptr- ::> BVType 32- ::> LLVMPointerType wptr)- -> forall r args reg.- OverrideSim p sym ext r args reg (RegValue sym UnitType)-callAssert assert_fail mvar bak (Empty :> _pfn :> _pfile :> _pline :> ptxt ) =- do let sym = backendGetSym bak- when failUponExit $- do mem <- readGlobal mvar- txt <- liftIO $ loadString bak mem (regValue ptxt) Nothing- let err = AssertFailureSimError "Call to assert()" (UTF8.toString txt)- liftIO $ addFailedAssertion bak err- liftIO $- do loc <- liftIO $ getCurrentProgramLoc sym- abortExecBecause $ EarlyExit loc- where- failUponExit :: Bool- failUponExit- | assert_fail- = abnormalExitBehavior ?intrinsicsOpts `elem` [AlwaysFail, OnlyAssertFail]- | otherwise- = abnormalExitBehavior ?intrinsicsOpts == AlwaysFail--callExit :: ( IsSymBackend sym bak- , ?intrinsicsOpts :: IntrinsicsOptions )- => bak- -> RegEntry sym (BVType 32)- -> OverrideSim p sym ext r args ret (RegValue sym UnitType)-callExit bak ec = liftIO $- do let sym = backendGetSym bak- when (abnormalExitBehavior ?intrinsicsOpts == AlwaysFail) $- do cond <- bvEq sym (regValue ec) =<< bvLit sym knownNat (BV.zero knownNat)- -- If the argument is non-zero, throw an assertion failure. Otherwise,- -- simply stop the current thread of execution.- assert bak cond "Call to exit() with non-zero argument"- loc <- getCurrentProgramLoc sym- abortExecBecause $ EarlyExit loc--callPrintf- :: ( IsSymBackend sym bak, HasPtrWidth wptr, HasLLVMAnn sym- , ?memOpts :: MemOptions )- => bak- -> GlobalVar Mem- -> RegEntry sym (LLVMPointerType wptr)- -> RegEntry sym (VectorType AnyType)- -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))-callPrintf bak mvar- (regValue -> strPtr)- (regValue -> valist) = do- mem <- readGlobal mvar- formatStr <- liftIO $ loadString bak mem strPtr Nothing- case parseDirectives formatStr of- Left err -> overrideError $ AssertFailureSimError "Format string parsing failed" err- Right ds -> do- ((str, n), mem') <- liftIO $ runStateT (executeDirectives (printfOps bak valist) ds) mem- writeGlobal mvar mem'- h <- printHandle <$> getContext- liftIO $ BS.hPutStr h str- liftIO $ bvLit (backendGetSym bak) knownNat (BV.mkBV knownNat (toInteger n))--printfOps :: ( IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr- , ?memOpts :: MemOptions )- => bak- -> V.Vector (AnyValue sym)- -> PrintfOperations (StateT (MemImpl sym) IO)-printfOps bak valist =- let sym = backendGetSym bak in- PrintfOperations- { printfUnsupported = \x -> lift $ addFailedAssertion bak- $ Unsupported GHC.callStack x-- , printfGetInteger = \i sgn _len ->- case valist V.!? (i-1) of- Just (AnyValue (LLVMPointerRepr w) x) ->- do bv <- liftIO (projectLLVM_bv bak x)- if sgn then- return $ BV.asSigned w <$> asBV bv- else- return $ BV.asUnsigned <$> asBV bv- Just (AnyValue tpr _) ->- lift $ addFailedAssertion bak- $ AssertFailureSimError- "Type mismatch in printf"- (unwords ["Expected integer, but got:", show tpr])- Nothing ->- lift $ addFailedAssertion bak- $ AssertFailureSimError- "Out-of-bounds argument access in printf"- (unwords ["Index:", show i])-- , printfGetFloat = \i _len ->- case valist V.!? (i-1) of- Just (AnyValue (FloatRepr (_fi :: FloatInfoRepr fi)) x) ->- do xr <- liftIO (iFloatToReal @_ @fi sym x)- return (asRational xr)- Just (AnyValue tpr _) ->- lift $ addFailedAssertion bak- $ AssertFailureSimError- "Type mismatch in printf."- (unwords ["Expected floating-point, but got:", show tpr])- Nothing ->- lift $ addFailedAssertion bak- $ AssertFailureSimError- "Out-of-bounds argument access in printf:"- (unwords ["Index:", show i])-- , printfGetString = \i numchars ->- case valist V.!? (i-1) of- Just (AnyValue PtrRepr ptr) ->- do mem <- get- liftIO $ loadString bak mem ptr numchars- Just (AnyValue tpr _) ->- lift $ addFailedAssertion bak- $ AssertFailureSimError- "Type mismatch in printf."- (unwords ["Expected char*, but got:", show tpr])- Nothing ->- lift $ addFailedAssertion bak- $ AssertFailureSimError- "Out-of-bounds argument access in printf:"- (unwords ["Index:", show i])-- , printfGetPointer = \i ->- case valist V.!? (i-1) of- Just (AnyValue PtrRepr ptr) ->- return $ show (G.ppPtr ptr)- Just (AnyValue tpr _) ->- lift $ addFailedAssertion bak- $ AssertFailureSimError- "Type mismatch in printf."- (unwords ["Expected void*, but got:", show tpr])- Nothing ->- lift $ addFailedAssertion bak- $ AssertFailureSimError- "Out-of-bounds argument access in printf:"- (unwords ["Index:", show i])-- , printfSetInteger = \i len v ->- case valist V.!? (i-1) of- Just (AnyValue PtrRepr ptr) ->- do mem <- get- case len of- Len_Byte -> do- let w8 = knownNat :: NatRepr 8- let tp = G.bitvectorType 1- x <- liftIO (llvmPointer_bv sym =<< bvLit sym w8 (BV.mkBV w8 (toInteger v)))- mem' <- liftIO $ doStore bak mem ptr (LLVMPointerRepr w8) tp noAlignment x- put mem'- Len_Short -> do- let w16 = knownNat :: NatRepr 16- let tp = G.bitvectorType 2- x <- liftIO (llvmPointer_bv sym =<< bvLit sym w16 (BV.mkBV w16 (toInteger v)))- mem' <- liftIO $ doStore bak mem ptr (LLVMPointerRepr w16) tp noAlignment x- put mem'- Len_NoMod -> do- let w32 = knownNat :: NatRepr 32- let tp = G.bitvectorType 4- x <- liftIO (llvmPointer_bv sym =<< bvLit sym w32 (BV.mkBV w32 (toInteger v)))- mem' <- liftIO $ doStore bak mem ptr (LLVMPointerRepr w32) tp noAlignment x- put mem'- Len_Long -> do- let w64 = knownNat :: NatRepr 64- let tp = G.bitvectorType 8- x <- liftIO (llvmPointer_bv sym =<< bvLit sym w64 (BV.mkBV w64 (toInteger v)))- mem' <- liftIO $ doStore bak mem ptr (LLVMPointerRepr w64) tp noAlignment x- put mem'- _ ->- lift $ addFailedAssertion bak- $ Unsupported GHC.callStack- $ unwords ["Unsupported size modifier in %n conversion:", show len]-- Just (AnyValue tpr _) ->- lift $ addFailedAssertion bak- $ AssertFailureSimError- "Type mismatch in printf."- (unwords ["Expected void*, but got:", show tpr])-- Nothing ->- lift $ addFailedAssertion bak- $ AssertFailureSimError- "Out-of-bounds argument access in printf:"- (unwords ["Index:", show i])- }----------------------------------------------------------------------------- *** Math--llvmCeilOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmCeilOverride =- [llvmOvr| double @ceil( double ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callCeil sym) args)--llvmCeilfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmCeilfOverride =- [llvmOvr| float @ceilf( float ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callCeil sym) args)---llvmFloorOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmFloorOverride =- [llvmOvr| double @floor( double ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callFloor sym) args)--llvmFloorfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmFloorfOverride =- [llvmOvr| float @floorf( float ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callFloor sym) args)--llvmFmafOverride ::- forall sym p- . IsSymInterface sym- => LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat- ::> FloatType SingleFloat- ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmFmafOverride =- [llvmOvr| float @fmaf( float, float, float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callFMA bak) args)--llvmFmaOverride ::- forall sym p- . IsSymInterface sym- => LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat- ::> FloatType DoubleFloat- ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmFmaOverride =- [llvmOvr| double @fma( double, double, double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callFMA bak) args)----- math.h defines isinf() and isnan() as macros, so you might think it unusual--- to provide function overrides for them. However, if you write, say,--- (isnan)(x) instead of isnan(x), Clang will compile the former as a direct--- function call rather than as a macro application. Some experimentation--- reveals that the isnan function's argument is always a double, so we give its--- argument the type double here to match this unstated convention. We follow--- suit similarly with isinf.------ Clang does not yet provide direct function call versions of isfinite() or--- isnormal(), so we do not provide overrides for them.--llvmIsinfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (BVType 32)-llvmIsinfOverride =- [llvmOvr| i32 @isinf( double ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callIsinf sym (knownNat @32)) args)---- __isinf and __isinff are like the isinf macro, except their arguments are--- known to be double or float, respectively. They are not mentioned in the--- POSIX source standard, only the binary standard. See--- http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/baselib---isinf.html and--- http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/baselib---isinff.html.-llvm__isinfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (BVType 32)-llvm__isinfOverride =- [llvmOvr| i32 @__isinf( double ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callIsinf sym (knownNat @32)) args)--llvm__isinffOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (BVType 32)-llvm__isinffOverride =- [llvmOvr| i32 @__isinff( float ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callIsinf sym (knownNat @32)) args)--llvmIsnanOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (BVType 32)-llvmIsnanOverride =- [llvmOvr| i32 @isnan( double ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callIsnan sym (knownNat @32)) args)---- __isnan and __isnanf are like the isnan macro, except their arguments are--- known to be double or float, respectively. They are not mentioned in the--- POSIX source standard, only the binary standard. See--- http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/baselib---isnan.html and--- http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/baselib---isnanf.html.-llvm__isnanOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (BVType 32)-llvm__isnanOverride =- [llvmOvr| i32 @__isnan( double ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callIsnan sym (knownNat @32)) args)--llvm__isnanfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (BVType 32)-llvm__isnanfOverride =- [llvmOvr| i32 @__isnanf( float ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callIsnan sym (knownNat @32)) args)---llvmSqrtOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmSqrtOverride =- [llvmOvr| double @sqrt( double ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callSqrt sym) args)--llvmSqrtfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmSqrtfOverride =- [llvmOvr| float @sqrtf( float ) |]- (\_memOps sym args -> Ctx.uncurryAssignment (callSqrt sym) args)--callSpecialFunction1 ::- forall fi p sym bak ext r args ret.- (IsSymBackend sym bak, KnownRepr FloatInfoRepr fi) =>- bak ->- W4.SpecialFunction (EmptyCtx ::> W4.R) ->- RegEntry sym (FloatType fi) ->- OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))-callSpecialFunction1 bak fn (regValue -> x) = liftIO $- iFloatSpecialFunction1 (backendGetSym bak) (knownRepr :: FloatInfoRepr fi) fn x--callSpecialFunction2 ::- forall fi p sym bak ext r args ret.- (IsSymBackend sym bak, KnownRepr FloatInfoRepr fi) =>- bak ->- W4.SpecialFunction (EmptyCtx ::> W4.R ::> W4.R) ->- RegEntry sym (FloatType fi) ->- RegEntry sym (FloatType fi) ->- OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))-callSpecialFunction2 bak fn (regValue -> x) (regValue -> y) = liftIO $- iFloatSpecialFunction2 (backendGetSym bak) (knownRepr :: FloatInfoRepr fi) fn x y--callCeil ::- forall fi p sym bak ext r args ret.- (IsSymBackend sym bak) =>- bak ->- RegEntry sym (FloatType fi) ->- OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))-callCeil bak (regValue -> x) = liftIO $ iFloatRound @_ @fi (backendGetSym bak) RTP x--callFloor ::- forall fi p sym bak ext r args ret.- (IsSymBackend sym bak) =>- bak ->- RegEntry sym (FloatType fi) ->- OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))-callFloor bak (regValue -> x) = liftIO $ iFloatRound @_ @fi (backendGetSym bak) RTN x---- | An implementation of @libc@'s @fma@ function.-callFMA ::- forall fi p sym bak ext r args ret- . IsSymBackend sym bak- => bak- -> RegEntry sym (FloatType fi)- -> RegEntry sym (FloatType fi)- -> RegEntry sym (FloatType fi)- -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))-callFMA bak (regValue -> x) (regValue -> y) (regValue -> z) = liftIO $- iFloatFMA @_ @fi (backendGetSym bak) defaultRM x y z---- | An implementation of @libc@'s @isinf@ macro. This returns @1@ when the--- argument is positive infinity, @-1@ when the argument is negative infinity,--- and zero otherwise.-callIsinf ::- forall fi w p sym bak ext r args ret.- (IsSymBackend sym bak, 1 <= w) =>- bak ->- NatRepr w ->- RegEntry sym (FloatType fi) ->- OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callIsinf bak w (regValue -> x) = liftIO $ do- let sym = backendGetSym bak- isInf <- iFloatIsInf @_ @fi sym x- isNeg <- iFloatIsNeg @_ @fi sym x- isPos <- iFloatIsPos @_ @fi sym x- isInfN <- andPred sym isInf isNeg- isInfP <- andPred sym isInf isPos- bvOne <- bvLit sym w (BV.one w)- bvNegOne <- bvNeg sym bvOne- bvZero <- bvLit sym w (BV.zero w)- res0 <- bvIte sym isInfP bvOne bvZero- bvIte sym isInfN bvNegOne res0--callIsnan ::- forall fi w p sym bak ext r args ret.- (IsSymBackend sym bak, 1 <= w) =>- bak ->- NatRepr w ->- RegEntry sym (FloatType fi) ->- OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callIsnan bak w (regValue -> x) = liftIO $ do- let sym = backendGetSym bak- isnan <- iFloatIsNaN @_ @fi sym x- bvOne <- bvLit sym w (BV.one w)- bvZero <- bvLit sym w (BV.zero w)- -- isnan() is allowed to return any nonzero value if the argument is NaN, and- -- out of all the possible nonzero values, `1` is certainly one of them.- bvIte sym isnan bvOne bvZero--callSqrt ::- forall fi p sym bak ext r args ret.- (IsSymBackend sym bak) =>- bak ->- RegEntry sym (FloatType fi) ->- OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))-callSqrt bak (regValue -> x) = liftIO $ iFloatSqrt @_ @fi (backendGetSym bak) defaultRM x----------------------------------------------------------------------------- **** Circular trigonometry functions---- sin(f)--llvmSinOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmSinOverride =- [llvmOvr| double @sin( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Sin) args)--llvmSinfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmSinfOverride =- [llvmOvr| float @sinf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Sin) args)---- cos(f)--llvmCosOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmCosOverride =- [llvmOvr| double @cos( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Cos) args)--llvmCosfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmCosfOverride =- [llvmOvr| float @cosf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Cos) args)---- tan(f)--llvmTanOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmTanOverride =- [llvmOvr| double @tan( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Tan) args)--llvmTanfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmTanfOverride =- [llvmOvr| float @tanf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Tan) args)---- asin(f)--llvmAsinOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmAsinOverride =- [llvmOvr| double @asin( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arcsin) args)--llvmAsinfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmAsinfOverride =- [llvmOvr| float @asinf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arcsin) args)---- acos(f)--llvmAcosOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmAcosOverride =- [llvmOvr| double @acos( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arccos) args)--llvmAcosfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmAcosfOverride =- [llvmOvr| float @acosf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arccos) args)---- atan(f)--llvmAtanOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmAtanOverride =- [llvmOvr| double @atan( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arctan) args)--llvmAtanfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmAtanfOverride =- [llvmOvr| float @atanf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arctan) args)----------------------------------------------------------------------------- **** Hyperbolic trigonometry functions---- sinh(f)--llvmSinhOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmSinhOverride =- [llvmOvr| double @sinh( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Sinh) args)--llvmSinhfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmSinhfOverride =- [llvmOvr| float @sinhf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Sinh) args)---- cosh(f)--llvmCoshOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmCoshOverride =- [llvmOvr| double @cosh( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Cosh) args)--llvmCoshfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmCoshfOverride =- [llvmOvr| float @coshf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Cosh) args)---- tanh(f)--llvmTanhOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmTanhOverride =- [llvmOvr| double @tanh( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Tanh) args)--llvmTanhfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmTanhfOverride =- [llvmOvr| float @tanhf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Tanh) args)---- asinh(f)--llvmAsinhOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmAsinhOverride =- [llvmOvr| double @asinh( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arcsinh) args)--llvmAsinhfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmAsinhfOverride =- [llvmOvr| float @asinhf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arcsinh) args)---- acosh(f)--llvmAcoshOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmAcoshOverride =- [llvmOvr| double @acosh( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arccosh) args)--llvmAcoshfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmAcoshfOverride =- [llvmOvr| float @acoshf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arccosh) args)---- atanh(f)--llvmAtanhOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmAtanhOverride =- [llvmOvr| double @atanh( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arctanh) args)--llvmAtanhfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmAtanhfOverride =- [llvmOvr| float @atanhf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Arctanh) args)----------------------------------------------------------------------------- **** Rectangular to polar coordinate conversion---- hypot(f)--llvmHypotOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmHypotOverride =- [llvmOvr| double @hypot( double, double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction2 bak W4.Hypot) args)--llvmHypotfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmHypotfOverride =- [llvmOvr| float @hypotf( float, float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction2 bak W4.Hypot) args)---- atan2(f)--llvmAtan2Override ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmAtan2Override =- [llvmOvr| double @atan2( double, double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction2 bak W4.Arctan2) args)--llvmAtan2fOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmAtan2fOverride =- [llvmOvr| float @atan2f( float, float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction2 bak W4.Arctan2) args)----------------------------------------------------------------------------- **** Exponential and logarithm functions---- pow(f)--llvmPowfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmPowfOverride =- [llvmOvr| float @powf( float, float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction2 bak W4.Pow) args)--llvmPowOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmPowOverride =- [llvmOvr| double @pow( double, double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction2 bak W4.Pow) args)---- exp(f)--llvmExpOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmExpOverride =- [llvmOvr| double @exp( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Exp) args)--llvmExpfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmExpfOverride =- [llvmOvr| float @expf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Exp) args)---- log(f)--llvmLogOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmLogOverride =- [llvmOvr| double @log( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Log) args)--llvmLogfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmLogfOverride =- [llvmOvr| float @logf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Log) args)---- expm1(f)--llvmExpm1Override ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmExpm1Override =- [llvmOvr| double @expm1( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Expm1) args)--llvmExpm1fOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmExpm1fOverride =- [llvmOvr| float @expm1f( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Expm1) args)---- log1p(f)--llvmLog1pOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmLog1pOverride =- [llvmOvr| double @log1p( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Log1p) args)--llvmLog1pfOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmLog1pfOverride =- [llvmOvr| float @log1pf( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Log1p) args)----------------------------------------------------------------------------- **** Base 2 exponential and logarithm---- exp2(f)--llvmExp2Override ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmExp2Override =- [llvmOvr| double @exp2( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Exp2) args)--llvmExp2fOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmExp2fOverride =- [llvmOvr| float @exp2f( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Exp2) args)---- log2(f)--llvmLog2Override ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmLog2Override =- [llvmOvr| double @log2( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Log2) args)--llvmLog2fOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmLog2fOverride =- [llvmOvr| float @log2f( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Log2) args)----------------------------------------------------------------------------- **** Base 10 exponential and logarithm---- exp10(f)--llvmExp10Override ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmExp10Override =- [llvmOvr| double @exp10( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Exp10) args)--llvmExp10fOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmExp10fOverride =- [llvmOvr| float @exp10f( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Exp10) args)---- log10(f)--llvmLog10Override ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType DoubleFloat)- (FloatType DoubleFloat)-llvmLog10Override =- [llvmOvr| double @log10( double ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Log10) args)--llvmLog10fOverride ::- IsSymInterface sym =>- LLVMOverride p sym- (EmptyCtx ::> FloatType SingleFloat)- (FloatType SingleFloat)-llvmLog10fOverride =- [llvmOvr| float @log10f( float ) |]- (\_memOps bak args -> Ctx.uncurryAssignment (callSpecialFunction1 bak W4.Log10) args)----------------------------------------------------------------------------- *** Other---- from OSX libc-llvmAssertRtnOverride- :: ( IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym- , ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> LLVMPointerType wptr- ::> BVType 32- ::> LLVMPointerType wptr)- UnitType-llvmAssertRtnOverride =- [llvmOvr| void @__assert_rtn( i8*, i8*, i32, i8* ) |]- (callAssert False)---- From glibc-llvmAssertFailOverride- :: ( IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym- , ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions )- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr- ::> LLVMPointerType wptr- ::> BVType 32- ::> LLVMPointerType wptr)- UnitType-llvmAssertFailOverride =- [llvmOvr| void @__assert_fail( i8*, i8*, i32, i8* ) |]- (callAssert True)---llvmAbortOverride- :: ( IsSymInterface sym- , ?intrinsicsOpts :: IntrinsicsOptions )- => LLVMOverride p sym EmptyCtx UnitType-llvmAbortOverride =- [llvmOvr| void @abort() |]- (\_ bak _args -> liftIO $- do let sym = backendGetSym bak- when (abnormalExitBehavior ?intrinsicsOpts == AlwaysFail) $- let err = AssertFailureSimError "Call to abort" "" in- assert bak (falsePred sym) err- loc <- getCurrentProgramLoc sym- abortExecBecause $ EarlyExit loc- )--llvmExitOverride- :: forall sym p- . ( IsSymInterface sym- , ?intrinsicsOpts :: IntrinsicsOptions )- => LLVMOverride p sym- (EmptyCtx ::> BVType 32)- UnitType-llvmExitOverride =- [llvmOvr| void @exit( i32 ) |]- (\_ bak args -> Ctx.uncurryAssignment (callExit bak) args)--llvmGetenvOverride- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr)- (LLVMPointerType wptr)-llvmGetenvOverride =- [llvmOvr| i8* @getenv( i8* ) |]- (\_ bak _args -> liftIO $ mkNullPointer (backendGetSym bak) PtrWidth)--llvmHtonlOverride ::- (IsSymInterface sym, ?lc :: TypeContext) =>- LLVMOverride p sym- (EmptyCtx ::> BVType 32)- (BVType 32)-llvmHtonlOverride =- [llvmOvr| i32 @htonl( i32 ) |]- (\_ bak args -> Ctx.uncurryAssignment (callBSwapIfLittleEndian bak (knownNat @4)) args)--llvmHtonsOverride ::- (IsSymInterface sym, ?lc :: TypeContext) =>- LLVMOverride p sym- (EmptyCtx ::> BVType 16)- (BVType 16)-llvmHtonsOverride =- [llvmOvr| i16 @htons( i16 ) |]- (\_ bak args -> Ctx.uncurryAssignment (callBSwapIfLittleEndian bak (knownNat @2)) args)--llvmNtohlOverride ::- (IsSymInterface sym, ?lc :: TypeContext) =>- LLVMOverride p sym- (EmptyCtx ::> BVType 32)- (BVType 32)-llvmNtohlOverride =- [llvmOvr| i32 @ntohl( i32 ) |]- (\_ bak args -> Ctx.uncurryAssignment (callBSwapIfLittleEndian bak (knownNat @4)) args)--llvmNtohsOverride ::- (IsSymInterface sym, ?lc :: TypeContext) =>- LLVMOverride p sym- (EmptyCtx ::> BVType 16)- (BVType 16)-llvmNtohsOverride =- [llvmOvr| i16 @ntohs( i16 ) |]- (\_ bak args -> Ctx.uncurryAssignment (callBSwapIfLittleEndian bak (knownNat @2)) args)--llvmAbsOverride ::- (IsSymInterface sym, HasLLVMAnn sym) =>- LLVMOverride p sym- (EmptyCtx ::> BVType 32)- (BVType 32)-llvmAbsOverride =- [llvmOvr| i32 @abs( i32 ) |]- (\mvar bak args ->- do callStack <- callStackFromMemVar' mvar- Ctx.uncurryAssignment (callLibcAbs bak callStack (knownNat @32)) args)---- @labs@ uses `long` as its argument and result type, so we need two overrides--- for @labs@. See Note [Overrides involving (unsigned) long] in--- Lang.Crucible.LLVM.Intrinsics.-llvmLAbsOverride_32 ::- (IsSymInterface sym, HasLLVMAnn sym) =>- LLVMOverride p sym- (EmptyCtx ::> BVType 32)- (BVType 32)-llvmLAbsOverride_32 =- [llvmOvr| i32 @labs( i32 ) |]- (\mvar bak args ->- do callStack <- callStackFromMemVar' mvar- Ctx.uncurryAssignment (callLibcAbs bak callStack (knownNat @32)) args)--llvmLAbsOverride_64 ::- (IsSymInterface sym, HasLLVMAnn sym) =>- LLVMOverride p sym- (EmptyCtx ::> BVType 64)- (BVType 64)-llvmLAbsOverride_64 =- [llvmOvr| i64 @labs( i64 ) |]- (\mvar bak args ->- do callStack <- callStackFromMemVar' mvar- Ctx.uncurryAssignment (callLibcAbs bak callStack (knownNat @64)) args)--llvmLLAbsOverride ::- (IsSymInterface sym, HasLLVMAnn sym) =>- LLVMOverride p sym- (EmptyCtx ::> BVType 64)- (BVType 64)-llvmLLAbsOverride =- [llvmOvr| i64 @llabs( i64 ) |]- (\mvar bak args ->- do callStack <- callStackFromMemVar' mvar- Ctx.uncurryAssignment (callLibcAbs bak callStack (knownNat @64)) args)--callBSwap ::- (1 <= width, IsSymBackend sym bak) =>- bak ->- NatRepr width ->- RegEntry sym (BVType (width * 8)) ->- OverrideSim p sym ext r args ret (RegValue sym (BVType (width * 8)))-callBSwap bak widthRepr (regValue -> vec) =- liftIO $ bvSwap (backendGetSym bak) widthRepr vec---- | This determines under what circumstances @callAbs@ should check if its--- argument is equal to the smallest signed integer of a particular size--- (e.g., @INT_MIN@), and if it is equal to that value, what kind of error--- should be reported.-data CheckAbsIntMin- = LibcAbsIntMinUB- -- ^ For the @abs@, @labs@, and @llabs@ functions, always check if the- -- argument is equal to @INT_MIN@. If so, report it as undefined- -- behavior per the C standard.- | LLVMAbsIntMinPoison Bool- -- ^ For the @llvm.abs.*@ family of LLVM intrinsics, check if the argument- -- is equal to @INT_MIN@ only when the 'Bool' argument is 'True'. If it- -- is 'True' and the argument is equal to @INT_MIN@, return poison.---- | The workhorse for the @abs@, @labs@, and @llabs@ functions, as well as the--- @llvm.abs.*@ family of overloaded intrinsics.-callAbs ::- forall w p sym bak ext r args ret.- (1 <= w, IsSymBackend sym bak, HasLLVMAnn sym) =>- bak ->- CallStack ->- CheckAbsIntMin ->- NatRepr w ->- RegEntry sym (BVType w) ->- OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callAbs bak callStack checkIntMin widthRepr (regValue -> src) = liftIO $ do- let sym = backendGetSym bak- bvIntMin <- bvLit sym widthRepr (BV.minSigned widthRepr)- isNotIntMin <- notPred sym =<< bvEq sym src bvIntMin-- when shouldCheckIntMin $ do- isNotIntMinUB <- annotateUB sym callStack ub isNotIntMin- let err = AssertFailureSimError "Undefined behavior encountered" $- show $ UB.explain ub- assert bak isNotIntMinUB err-- isSrcNegative <- bvIsNeg sym src- srcNegated <- bvNeg sym src- bvIte sym isSrcNegative srcNegated src- where- shouldCheckIntMin :: Bool- shouldCheckIntMin =- case checkIntMin of- LibcAbsIntMinUB -> True- LLVMAbsIntMinPoison shouldCheck -> shouldCheck-- ub :: UB.UndefinedBehavior (RegValue' sym)- ub = case checkIntMin of- LibcAbsIntMinUB ->- UB.AbsIntMin $ RV src- LLVMAbsIntMinPoison{} ->- UB.PoisonValueCreated $ Poison.LLVMAbsIntMin $ RV src--callLibcAbs ::- (1 <= w, IsSymBackend sym bak, HasLLVMAnn sym) =>- bak ->- CallStack ->- NatRepr w ->- RegEntry sym (BVType w) ->- OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callLibcAbs bak callStack = callAbs bak callStack LibcAbsIntMinUB--callLLVMAbs ::- (1 <= w, IsSymBackend sym bak, HasLLVMAnn sym) =>- bak ->- CallStack ->- NatRepr w ->- RegEntry sym (BVType w) ->- RegEntry sym (BVType 1) ->- OverrideSim p sym ext r args ret (RegValue sym (BVType w))-callLLVMAbs bak callStack widthRepr src (regValue -> isIntMinPoison) = do- shouldCheckIntMin <- liftIO $- -- Per https://releases.llvm.org/12.0.0/docs/LangRef.html#id451, the second- -- argument must be a constant.- case asBV isIntMinPoison of- Just bv -> pure (bv /= BV.zero (knownNat @1))- Nothing -> malformedLLVMModule- "Call to llvm.abs.* with non-constant second argument"- [printSymExpr isIntMinPoison]- callAbs bak callStack (LLVMAbsIntMinPoison shouldCheckIntMin) widthRepr src---- | If the data layout is little-endian, run 'callBSwap' on the input.--- Otherwise, return the input unchanged. This is the workhorse for the--- @hton{s,l}@ and @ntoh{s,l}@ overrides.-callBSwapIfLittleEndian ::- (1 <= width, IsSymBackend sym bak, ?lc :: TypeContext) =>- bak ->- NatRepr width ->- RegEntry sym (BVType (width * 8)) ->- OverrideSim p sym ext r args ret (RegValue sym (BVType (width * 8)))-callBSwapIfLittleEndian bak widthRepr vec =- case (llvmDataLayout ?lc)^.intLayout of- BigEndian -> pure (regValue vec)- LittleEndian -> callBSwap bak widthRepr vec--------------------------------------------------------------------------------- atexit stuff--cxa_atexitOverride- :: (IsSymInterface sym, HasPtrWidth wptr)- => LLVMOverride p sym- (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr ::> LLVMPointerType wptr)- (BVType 32)-cxa_atexitOverride =- [llvmOvr| i32 @__cxa_atexit( void (i8*)*, i8*, i8* ) |]- (\_ bak _args -> liftIO $ bvLit (backendGetSym bak) knownNat (BV.zero knownNat))+import What4.ProgramLoc (plSourceLoc)+import qualified What4.SpecialFunctions as W4++import Lang.Crucible.Backend+import Lang.Crucible.CFG.Common+import Lang.Crucible.Types+import Lang.Crucible.Simulator.ExecutionTree+import Lang.Crucible.Simulator.OverrideSim+import Lang.Crucible.Simulator.RegMap+import Lang.Crucible.Simulator.SimError++import Lang.Crucible.LLVM.Bytes+import Lang.Crucible.LLVM.DataLayout+import qualified Lang.Crucible.LLVM.Errors.Poison as Poison+import qualified Lang.Crucible.LLVM.Errors.UndefinedBehavior as UB+import Lang.Crucible.LLVM.MalformedLLVMModule+import Lang.Crucible.LLVM.MemModel+import Lang.Crucible.LLVM.MemModel.CallStack (CallStack)+import qualified Lang.Crucible.LLVM.MemModel.Type as G+import qualified Lang.Crucible.LLVM.MemModel.Generic as G+import Lang.Crucible.LLVM.MemModel.Partial+import qualified Lang.Crucible.LLVM.MemModel.Pointer as Ptr+import Lang.Crucible.LLVM.Printf+import Lang.Crucible.LLVM.QQ( llvmOvr )+import Lang.Crucible.LLVM.TypeContext++import Lang.Crucible.LLVM.Intrinsics.Common+import Lang.Crucible.LLVM.Intrinsics.Options++-- | All libc overrides.+--+-- This list is useful to other Crucible frontends based on the LLVM memory+-- model (e.g., Macaw).+libc_overrides ::+ ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?lc :: TypeContext, ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions ) =>+ [SomeLLVMOverride p sym ext]+libc_overrides =+ [ SomeLLVMOverride llvmAbortOverride+ , SomeLLVMOverride llvmAssertRtnOverride+ , SomeLLVMOverride llvmAssertFailOverride+ , SomeLLVMOverride llvmMemcpyOverride+ , SomeLLVMOverride llvmMemcpyChkOverride+ , SomeLLVMOverride llvmMemmoveOverride+ , SomeLLVMOverride llvmMemsetOverride+ , SomeLLVMOverride llvmMemsetChkOverride+ , SomeLLVMOverride llvmMallocOverride+ , SomeLLVMOverride llvmCallocOverride+ , SomeLLVMOverride llvmFreeOverride+ , SomeLLVMOverride llvmReallocOverride+ , SomeLLVMOverride llvmStrlenOverride+ , SomeLLVMOverride llvmPrintfOverride+ , SomeLLVMOverride llvmPrintfChkOverride+ , SomeLLVMOverride llvmPutsOverride+ , SomeLLVMOverride llvmPutCharOverride+ , SomeLLVMOverride llvmExitOverride+ , SomeLLVMOverride llvmGetenvOverride+ , SomeLLVMOverride llvmHtonlOverride+ , SomeLLVMOverride llvmHtonsOverride+ , SomeLLVMOverride llvmNtohlOverride+ , SomeLLVMOverride llvmNtohsOverride+ , SomeLLVMOverride llvmAbsOverride+ , SomeLLVMOverride llvmLAbsOverride_32+ , SomeLLVMOverride llvmLAbsOverride_64+ , SomeLLVMOverride llvmLLAbsOverride++ , SomeLLVMOverride llvmCeilOverride+ , SomeLLVMOverride llvmCeilfOverride+ , SomeLLVMOverride llvmFloorOverride+ , SomeLLVMOverride llvmFloorfOverride+ , SomeLLVMOverride llvmFmaOverride+ , SomeLLVMOverride llvmFmafOverride+ , SomeLLVMOverride llvmIsinfOverride+ , SomeLLVMOverride llvm__isinfOverride+ , SomeLLVMOverride llvm__isinffOverride+ , SomeLLVMOverride llvmIsnanOverride+ , SomeLLVMOverride llvm__isnanOverride+ , SomeLLVMOverride llvm__isnanfOverride+ , SomeLLVMOverride llvm__isnandOverride+ , SomeLLVMOverride llvmSqrtOverride+ , SomeLLVMOverride llvmSqrtfOverride+ , SomeLLVMOverride llvmSinOverride+ , SomeLLVMOverride llvmSinfOverride+ , SomeLLVMOverride llvmCosOverride+ , SomeLLVMOverride llvmCosfOverride+ , SomeLLVMOverride llvmTanOverride+ , SomeLLVMOverride llvmTanfOverride+ , SomeLLVMOverride llvmAsinOverride+ , SomeLLVMOverride llvmAsinfOverride+ , SomeLLVMOverride llvmAcosOverride+ , SomeLLVMOverride llvmAcosfOverride+ , SomeLLVMOverride llvmAtanOverride+ , SomeLLVMOverride llvmAtanfOverride+ , SomeLLVMOverride llvmSinhOverride+ , SomeLLVMOverride llvmSinhfOverride+ , SomeLLVMOverride llvmCoshOverride+ , SomeLLVMOverride llvmCoshfOverride+ , SomeLLVMOverride llvmTanhOverride+ , SomeLLVMOverride llvmTanhfOverride+ , SomeLLVMOverride llvmAsinhOverride+ , SomeLLVMOverride llvmAsinhfOverride+ , SomeLLVMOverride llvmAcoshOverride+ , SomeLLVMOverride llvmAcoshfOverride+ , SomeLLVMOverride llvmAtanhOverride+ , SomeLLVMOverride llvmAtanhfOverride+ , SomeLLVMOverride llvmHypotOverride+ , SomeLLVMOverride llvmHypotfOverride+ , SomeLLVMOverride llvmAtan2Override+ , SomeLLVMOverride llvmAtan2fOverride+ , SomeLLVMOverride llvmPowfOverride+ , SomeLLVMOverride llvmPowOverride+ , SomeLLVMOverride llvmExpOverride+ , SomeLLVMOverride llvmExpfOverride+ , SomeLLVMOverride llvmLogOverride+ , SomeLLVMOverride llvmLogfOverride+ , SomeLLVMOverride llvmExpm1Override+ , SomeLLVMOverride llvmExpm1fOverride+ , SomeLLVMOverride llvmLog1pOverride+ , SomeLLVMOverride llvmLog1pfOverride+ , SomeLLVMOverride llvmExp2Override+ , SomeLLVMOverride llvmExp2fOverride+ , SomeLLVMOverride llvmLog2Override+ , SomeLLVMOverride llvmLog2fOverride+ , SomeLLVMOverride llvmExp10Override+ , SomeLLVMOverride llvmExp10fOverride+ , SomeLLVMOverride llvm__exp10Override+ , SomeLLVMOverride llvm__exp10fOverride+ , SomeLLVMOverride llvmLog10Override+ , SomeLLVMOverride llvmLog10fOverride++ , SomeLLVMOverride cxa_atexitOverride+ , SomeLLVMOverride posixMemalignOverride+ ]++------------------------------------------------------------------------+-- ** Declarations+++llvmMemcpyOverride+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> LLVMPointerType wptr+ ::> BVType wptr)+ (LLVMPointerType wptr)+llvmMemcpyOverride =+ [llvmOvr| i8* @memcpy( i8*, i8*, size_t ) |]+ (\memOps args ->+ do sym <- getSymInterface+ volatile <- liftIO $ RegEntry knownRepr <$> bvZero sym knownNat+ Ctx.uncurryAssignment (callMemcpy memOps)+ (args :> volatile)+ return $ regValue $ args^._1 -- return first argument+ )+++llvmMemcpyChkOverride+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> LLVMPointerType wptr+ ::> BVType wptr+ ::> BVType wptr)+ (LLVMPointerType wptr)+llvmMemcpyChkOverride =+ [llvmOvr| i8* @__memcpy_chk ( i8*, i8*, size_t, size_t ) |]+ (\memOps args ->+ do let args' = Empty :> (args^._1) :> (args^._2) :> (args^._3)+ sym <- getSymInterface+ volatile <- liftIO $ RegEntry knownRepr <$> bvZero sym knownNat+ Ctx.uncurryAssignment (callMemcpy memOps)+ (args' :> volatile)+ return $ regValue $ args^._1 -- return first argument+ )++llvmMemmoveOverride+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> (LLVMPointerType wptr)+ ::> (LLVMPointerType wptr)+ ::> BVType wptr)+ (LLVMPointerType wptr)+llvmMemmoveOverride =+ [llvmOvr| i8* @memmove( i8*, i8*, size_t ) |]+ (\memOps args ->+ do sym <- getSymInterface+ volatile <- liftIO (RegEntry knownRepr <$> bvZero sym knownNat)+ Ctx.uncurryAssignment (callMemmove memOps)+ (args :> volatile)+ return $ regValue $ args^._1 -- return first argument+ )++llvmMemsetOverride :: forall p sym ext wptr.+ (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> BVType 32+ ::> BVType wptr)+ (LLVMPointerType wptr)+llvmMemsetOverride =+ [llvmOvr| i8* @memset( i8*, i32, size_t ) |]+ (\memOps args ->+ do sym <- getSymInterface+ LeqProof <- return (leqTrans @9 @16 @wptr LeqProof LeqProof)+ let dest = args^._1+ val <- liftIO (RegEntry knownRepr <$> bvTrunc sym (knownNat @8) (regValue (args^._2)))+ let len = args^._3+ volatile <- liftIO+ (RegEntry knownRepr <$> bvZero sym knownNat)+ callMemset memOps dest val len volatile+ return (regValue dest)+ )++llvmMemsetChkOverride+ :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> BVType 32+ ::> BVType wptr+ ::> BVType wptr)+ (LLVMPointerType wptr)+llvmMemsetChkOverride =+ [llvmOvr| i8* @__memset_chk( i8*, i32, size_t, size_t ) |]+ (\memOps args ->+ do sym <- getSymInterface+ let dest = args^._1+ val <- liftIO+ (RegEntry knownRepr <$> bvTrunc sym knownNat (regValue (args^._2)))+ let len = args^._3+ volatile <- liftIO+ (RegEntry knownRepr <$> bvZero sym knownNat)+ callMemset memOps dest val len volatile+ return (regValue dest)+ )++------------------------------------------------------------------------+-- *** Allocation++llvmCallocOverride+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?lc :: TypeContext, ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> BVType wptr ::> BVType wptr)+ (LLVMPointerType wptr)+llvmCallocOverride =+ let alignment = maxAlignment (llvmDataLayout ?lc) in+ [llvmOvr| i8* @calloc( size_t, size_t ) |]+ (\memOps args -> Ctx.uncurryAssignment (callCalloc memOps alignment) args)+++llvmReallocOverride+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?lc :: TypeContext, ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> BVType wptr)+ (LLVMPointerType wptr)+llvmReallocOverride =+ let alignment = maxAlignment (llvmDataLayout ?lc) in+ [llvmOvr| i8* @realloc( i8*, size_t ) |]+ (\memOps args -> Ctx.uncurryAssignment (callRealloc memOps alignment) args)++llvmMallocOverride+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?lc :: TypeContext, ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> BVType wptr)+ (LLVMPointerType wptr)+llvmMallocOverride =+ let alignment = maxAlignment (llvmDataLayout ?lc) in+ [llvmOvr| i8* @malloc( size_t ) |]+ (\memOps args -> Ctx.uncurryAssignment (callMalloc memOps alignment) args)++posixMemalignOverride ::+ ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?lc :: TypeContext, ?memOpts :: MemOptions ) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> BVType wptr+ ::> BVType wptr)+ (BVType 32)+posixMemalignOverride =+ [llvmOvr| i32 @posix_memalign( i8**, size_t, size_t ) |]+ (\memOps args -> Ctx.uncurryAssignment (callPosixMemalign memOps) args)+++llvmFreeOverride+ :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr)+ UnitType+llvmFreeOverride =+ [llvmOvr| void @free( i8* ) |]+ (\memOps args -> Ctx.uncurryAssignment (callFree memOps) args)++------------------------------------------------------------------------+-- *** Strings and I/O++llvmPrintfOverride+ :: ( IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> VectorType AnyType)+ (BVType 32)+llvmPrintfOverride =+ [llvmOvr| i32 @printf( i8*, ... ) |]+ (\memOps args -> Ctx.uncurryAssignment (callPrintf memOps) args)++llvmPrintfChkOverride+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> BVType 32+ ::> LLVMPointerType wptr+ ::> VectorType AnyType)+ (BVType 32)+llvmPrintfChkOverride =+ [llvmOvr| i32 @__printf_chk( i32, i8*, ... ) |]+ (\memOps args -> Ctx.uncurryAssignment (\_flg -> callPrintf memOps) args)+++llvmPutCharOverride+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext (EmptyCtx ::> BVType 32) (BVType 32)+llvmPutCharOverride =+ [llvmOvr| i32 @putchar( i32 ) |]+ (\memOps args -> Ctx.uncurryAssignment (callPutChar memOps) args)+++llvmPutsOverride+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr) (BVType 32)+llvmPutsOverride =+ [llvmOvr| i32 @puts( i8* ) |]+ (\memOps args -> Ctx.uncurryAssignment (callPuts memOps) args)++llvmStrlenOverride+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr) (BVType wptr)+llvmStrlenOverride =+ [llvmOvr| size_t @strlen( i8* ) |]+ (\memOps args -> Ctx.uncurryAssignment (callStrlen memOps) args)++------------------------------------------------------------------------+-- ** Implementations++------------------------------------------------------------------------+-- *** Allocation++callRealloc+ :: ( IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym+ , ?memOpts :: MemOptions )+ => GlobalVar Mem+ -> Alignment+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (BVType wptr)+ -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))+callRealloc mvar alignment (regValue -> ptr) (regValue -> sz) =+ ovrWithBackend $ \bak -> do+ let sym = backendGetSym bak+ szZero <- liftIO (notPred sym =<< bvIsNonzero sym sz)+ ptrNull <- liftIO (ptrIsNull sym PtrWidth ptr)+ loc <- liftIO (plSourceLoc <$> getCurrentProgramLoc sym)+ let displayString = "<realloc> " ++ show loc++ symbolicBranches emptyRegMap+ -- If the pointer is null, behave like malloc+ [ ( ptrNull+ , modifyGlobal mvar $ \mem -> liftIO $ doMalloc bak G.HeapAlloc G.Mutable displayString mem sz alignment+ , Nothing+ )++ -- If the size is zero, behave like malloc (of zero bytes) then free+ , (szZero+ , modifyGlobal mvar $ \mem -> liftIO $+ do (newp, mem1) <- doMalloc bak G.HeapAlloc G.Mutable displayString mem sz alignment+ mem2 <- doFree bak mem1 ptr+ return (newp, mem2)+ , Nothing+ )++ -- Otherwise, allocate a new region, memcopy `sz` bytes and free the old pointer+ , (truePred sym+ , modifyGlobal mvar $ \mem -> liftIO $+ do (newp, mem1) <- doMalloc bak G.HeapAlloc G.Mutable displayString mem sz alignment+ mem2 <- uncheckedMemcpy sym mem1 newp ptr sz+ mem3 <- doFree bak mem2 ptr+ return (newp, mem3)+ , Nothing)+ ]+++callPosixMemalign+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?lc :: TypeContext, ?memOpts :: MemOptions )+ => GlobalVar Mem+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (BVType wptr)+ -> RegEntry sym (BVType wptr)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))+callPosixMemalign mvar (regValue -> outPtr) (regValue -> align) (regValue -> sz) =+ ovrWithBackend $ \bak ->+ let sym = backendGetSym bak in+ case asBV align of+ Nothing -> fail $ unwords ["posix_memalign: alignment value must be concrete:", show (printSymExpr align)]+ Just concrete_align ->+ case toAlignment (toBytes (BV.asUnsigned concrete_align)) of+ Nothing -> fail $ unwords ["posix_memalign: invalid alignment value:", show concrete_align]+ Just a ->+ let dl = llvmDataLayout ?lc in+ modifyGlobal mvar $ \mem -> liftIO $+ do loc <- plSourceLoc <$> getCurrentProgramLoc sym+ let displayString = "<posix_memaign> " ++ show loc+ (p, mem') <- doMalloc bak G.HeapAlloc G.Mutable displayString mem sz a+ mem'' <- storeRaw bak mem' outPtr (bitvectorType (dl^.ptrSize)) (dl^.ptrAlign) (ptrToPtrVal p)+ z <- bvZero sym knownNat+ return (z, mem'')++callMalloc+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => GlobalVar Mem+ -> Alignment+ -> RegEntry sym (BVType wptr)+ -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))+callMalloc mvar alignment (regValue -> sz) =+ ovrWithBackend $ \bak ->+ modifyGlobal mvar $ \mem -> liftIO $+ do loc <- plSourceLoc <$> getCurrentProgramLoc (backendGetSym bak)+ let displayString = "<malloc> " ++ show loc+ doMalloc bak G.HeapAlloc G.Mutable displayString mem sz alignment++callCalloc+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => GlobalVar Mem+ -> Alignment+ -> RegEntry sym (BVType wptr)+ -> RegEntry sym (BVType wptr)+ -> OverrideSim p sym ext r args ret (RegValue sym (LLVMPointerType wptr))+callCalloc mvar alignment+ (regValue -> sz)+ (regValue -> num) =+ ovrWithBackend $ \bak ->+ modifyGlobal mvar $ \mem -> liftIO $+ doCalloc bak mem sz num alignment++callFree+ :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)+ => GlobalVar Mem+ -> RegEntry sym (LLVMPointerType wptr)+ -> OverrideSim p sym ext r args ret ()+callFree mvar+ (regValue -> ptr) =+ ovrWithBackend $ \bak ->+ modifyGlobal mvar $ \mem -> liftIO $+ do mem' <- doFree bak mem ptr+ return ((), mem')++------------------------------------------------------------------------+-- *** Memory manipulation++callMemcpy+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => GlobalVar Mem+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType 1)+ -> OverrideSim p sym ext r args ret ()+callMemcpy mvar+ (regValue -> dest)+ (regValue -> src)+ (RegEntry (BVRepr w) len)+ _volatile =+ ovrWithBackend $ \bak ->+ modifyGlobal mvar $ \mem -> liftIO $+ do mem' <- doMemcpy bak w mem True dest src len+ return ((), mem')++-- NB the only difference between memcpy and memove+-- is that memmove does not assert that the memory+-- ranges are disjoint. The underlying operation+-- works correctly in both cases.+callMemmove+ :: ( IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => GlobalVar Mem+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType 1)+ -> OverrideSim p sym ext r args ret ()+callMemmove mvar+ (regValue -> dest)+ (regValue -> src)+ (RegEntry (BVRepr w) len)+ _volatile =+ -- FIXME? add assertions about alignment+ ovrWithBackend $ \bak ->+ modifyGlobal mvar $ \mem -> liftIO $+ do mem' <- doMemcpy bak w mem False dest src len+ return ((), mem')++callMemset+ :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr)+ => GlobalVar Mem+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (BVType 8)+ -> RegEntry sym (BVType w)+ -> RegEntry sym (BVType 1)+ -> OverrideSim p sym ext r args ret ()+callMemset mvar+ (regValue -> dest)+ (regValue -> val)+ (RegEntry (BVRepr w) len)+ _volatile =+ ovrWithBackend $ \bak ->+ modifyGlobal mvar $ \mem -> liftIO $+ do mem' <- doMemset bak w mem dest val len+ return ((), mem')++------------------------------------------------------------------------+-- *** Strings and I/O++callPutChar+ :: IsSymInterface sym+ => GlobalVar Mem+ -> RegEntry sym (BVType 32)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))+callPutChar _mvar+ (regValue -> ch) = do+ h <- printHandle <$> getContext+ let chval = maybe '?' (toEnum . fromInteger) (BV.asUnsigned <$> asBV ch)+ liftIO $ hPutChar h chval+ return ch++callPuts+ :: ( IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym+ , ?memOpts :: MemOptions )+ => GlobalVar Mem+ -> RegEntry sym (LLVMPointerType wptr)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))+callPuts mvar+ (regValue -> strPtr) =+ ovrWithBackend $ \bak -> do+ mem <- readGlobal mvar+ str <- liftIO $ loadString bak mem strPtr Nothing+ h <- printHandle <$> getContext+ liftIO $ hPutStrLn h (UTF8.toString str)+ -- return non-negative value on success+ liftIO $ bvLit (backendGetSym bak) knownNat (BV.one knownNat)++callStrlen+ :: ( IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym+ , ?memOpts :: MemOptions )+ => GlobalVar Mem+ -> RegEntry sym (LLVMPointerType wptr)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType wptr))+callStrlen mvar (regValue -> strPtr) =+ ovrWithBackend $ \bak -> do+ mem <- readGlobal mvar+ liftIO $ strLen bak mem strPtr++callAssert+ :: ( IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym+ , ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions )+ => GlobalVar Mem+ -> Ctx.Assignment (RegEntry sym)+ (EmptyCtx ::> LLVMPointerType wptr+ ::> LLVMPointerType wptr+ ::> BVType 32+ ::> LLVMPointerType wptr)+ -> forall r args reg.+ OverrideSim p sym ext r args reg (RegValue sym UnitType)+callAssert mvar (Empty :> _pfn :> _pfile :> _pline :> ptxt ) =+ ovrWithBackend $ \bak -> do+ let sym = backendGetSym bak+ when failUponExit $+ do mem <- readGlobal mvar+ txt <- liftIO $ loadString bak mem (regValue ptxt) Nothing+ let err = AssertFailureSimError "Call to assert()" (UTF8.toString txt)+ liftIO $ addFailedAssertion bak err+ liftIO $+ do loc <- liftIO $ getCurrentProgramLoc sym+ abortExecBecause $ EarlyExit loc+ where+ failUponExit :: Bool+ failUponExit+ = abnormalExitBehavior ?intrinsicsOpts `elem` [AlwaysFail, OnlyAssertFail]++callExit :: ( IsSymInterface sym+ , ?intrinsicsOpts :: IntrinsicsOptions )+ => RegEntry sym (BVType 32)+ -> OverrideSim p sym ext r args ret (RegValue sym UnitType)+callExit ec =+ ovrWithBackend $ \bak -> liftIO $ do+ let sym = backendGetSym bak+ when (abnormalExitBehavior ?intrinsicsOpts == AlwaysFail) $+ do cond <- bvEq sym (regValue ec) =<< bvZero sym knownNat+ -- If the argument is non-zero, throw an assertion failure. Otherwise,+ -- simply stop the current thread of execution.+ assert bak cond "Call to exit() with non-zero argument"+ loc <- getCurrentProgramLoc sym+ abortExecBecause $ EarlyExit loc++callPrintf+ :: ( IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym+ , ?memOpts :: MemOptions )+ => GlobalVar Mem+ -> RegEntry sym (LLVMPointerType wptr)+ -> RegEntry sym (VectorType AnyType)+ -> OverrideSim p sym ext r args ret (RegValue sym (BVType 32))+callPrintf mvar+ (regValue -> strPtr)+ (regValue -> valist) =+ ovrWithBackend $ \bak -> do+ mem <- readGlobal mvar+ formatStr <- liftIO $ loadString bak mem strPtr Nothing+ case parseDirectives formatStr of+ Left err -> overrideError $ AssertFailureSimError "Format string parsing failed" err+ Right ds -> do+ ((str, n), mem') <- liftIO $ runStateT (executeDirectives (printfOps bak valist) ds) mem+ writeGlobal mvar mem'+ h <- printHandle <$> getContext+ liftIO $ BS.hPutStr h str+ liftIO $ bvLit (backendGetSym bak) knownNat (BV.mkBV knownNat (toInteger n))++printfOps :: ( IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr+ , ?memOpts :: MemOptions )+ => bak+ -> V.Vector (AnyValue sym)+ -> PrintfOperations (StateT (MemImpl sym) IO)+printfOps bak valist =+ let sym = backendGetSym bak in+ PrintfOperations+ { printfUnsupported = \x -> lift $ addFailedAssertion bak+ $ Unsupported GHC.callStack x++ , printfGetInteger = \i sgn _len ->+ case valist V.!? (i-1) of+ Just (AnyValue (LLVMPointerRepr w) p@(LLVMPointer _blk bv)) ->+ do isBv <- liftIO (Ptr.ptrIsBv sym p)+ liftIO $ assert bak isBv $+ AssertFailureSimError+ "Passed a pointer to printf where a bitvector was expected"+ ""+ if sgn then+ return $ BV.asSigned w <$> asBV bv+ else+ return $ BV.asUnsigned <$> asBV bv+ Just (AnyValue tpr _) ->+ lift $ addFailedAssertion bak+ $ AssertFailureSimError+ "Type mismatch in printf"+ (unwords ["Expected integer, but got:", show tpr])+ Nothing ->+ lift $ addFailedAssertion bak+ $ AssertFailureSimError+ "Out-of-bounds argument access in printf"+ (unwords ["Index:", show i])++ , printfGetFloat = \i _len ->+ case valist V.!? (i-1) of+ Just (AnyValue (FloatRepr (_fi :: FloatInfoRepr fi)) x) ->+ do xr <- liftIO (iFloatToReal @_ @fi sym x)+ return (asRational xr)+ Just (AnyValue tpr _) ->+ lift $ addFailedAssertion bak+ $ AssertFailureSimError+ "Type mismatch in printf."+ (unwords ["Expected floating-point, but got:", show tpr])+ Nothing ->+ lift $ addFailedAssertion bak+ $ AssertFailureSimError+ "Out-of-bounds argument access in printf:"+ (unwords ["Index:", show i])++ , printfGetString = \i numchars ->+ case valist V.!? (i-1) of+ Just (AnyValue PtrRepr ptr) ->+ do mem <- get+ liftIO $ loadString bak mem ptr numchars+ Just (AnyValue tpr _) ->+ lift $ addFailedAssertion bak+ $ AssertFailureSimError+ "Type mismatch in printf."+ (unwords ["Expected char*, but got:", show tpr])+ Nothing ->+ lift $ addFailedAssertion bak+ $ AssertFailureSimError+ "Out-of-bounds argument access in printf:"+ (unwords ["Index:", show i])++ , printfGetPointer = \i ->+ case valist V.!? (i-1) of+ Just (AnyValue PtrRepr ptr) ->+ return $ show (G.ppPtr ptr)+ Just (AnyValue tpr _) ->+ lift $ addFailedAssertion bak+ $ AssertFailureSimError+ "Type mismatch in printf."+ (unwords ["Expected void*, but got:", show tpr])+ Nothing ->+ lift $ addFailedAssertion bak+ $ AssertFailureSimError+ "Out-of-bounds argument access in printf:"+ (unwords ["Index:", show i])++ , printfSetInteger = \i len v ->+ case valist V.!? (i-1) of+ Just (AnyValue PtrRepr ptr) ->+ do mem <- get+ case len of+ Len_Byte -> do+ let w8 = knownNat :: NatRepr 8+ let tp = G.bitvectorType 1+ x <- liftIO (llvmPointer_bv sym =<< bvLit sym w8 (BV.mkBV w8 (toInteger v)))+ mem' <- liftIO $ doStore bak mem ptr (LLVMPointerRepr w8) tp noAlignment x+ put mem'+ Len_Short -> do+ let w16 = knownNat :: NatRepr 16+ let tp = G.bitvectorType 2+ x <- liftIO (llvmPointer_bv sym =<< bvLit sym w16 (BV.mkBV w16 (toInteger v)))+ mem' <- liftIO $ doStore bak mem ptr (LLVMPointerRepr w16) tp noAlignment x+ put mem'+ Len_NoMod -> do+ let w32 = knownNat :: NatRepr 32+ let tp = G.bitvectorType 4+ x <- liftIO (llvmPointer_bv sym =<< bvLit sym w32 (BV.mkBV w32 (toInteger v)))+ mem' <- liftIO $ doStore bak mem ptr (LLVMPointerRepr w32) tp noAlignment x+ put mem'+ Len_Long -> do+ let w64 = knownNat :: NatRepr 64+ let tp = G.bitvectorType 8+ x <- liftIO (llvmPointer_bv sym =<< bvLit sym w64 (BV.mkBV w64 (toInteger v)))+ mem' <- liftIO $ doStore bak mem ptr (LLVMPointerRepr w64) tp noAlignment x+ put mem'+ _ ->+ lift $ addFailedAssertion bak+ $ Unsupported GHC.callStack+ $ unwords ["Unsupported size modifier in %n conversion:", show len]++ Just (AnyValue tpr _) ->+ lift $ addFailedAssertion bak+ $ AssertFailureSimError+ "Type mismatch in printf."+ (unwords ["Expected void*, but got:", show tpr])++ Nothing ->+ lift $ addFailedAssertion bak+ $ AssertFailureSimError+ "Out-of-bounds argument access in printf:"+ (unwords ["Index:", show i])+ }++------------------------------------------------------------------------+-- *** Math++llvmCeilOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmCeilOverride =+ [llvmOvr| double @ceil( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment callCeil args)++llvmCeilfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmCeilfOverride =+ [llvmOvr| float @ceilf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment callCeil args)+++llvmFloorOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmFloorOverride =+ [llvmOvr| double @floor( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment callFloor args)++llvmFloorfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmFloorfOverride =+ [llvmOvr| float @floorf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment callFloor args)++llvmFmafOverride ::+ forall sym p ext+ . IsSymInterface sym+ => LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat+ ::> FloatType SingleFloat+ ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmFmafOverride =+ [llvmOvr| float @fmaf( float, float, float ) |]+ (\_memOps args -> Ctx.uncurryAssignment callFMA args)++llvmFmaOverride ::+ forall sym p ext+ . IsSymInterface sym+ => LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat+ ::> FloatType DoubleFloat+ ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmFmaOverride =+ [llvmOvr| double @fma( double, double, double ) |]+ (\_memOps args -> Ctx.uncurryAssignment callFMA args)+++-- math.h defines isinf() and isnan() as macros, so you might think it unusual+-- to provide function overrides for them. However, if you write, say,+-- (isnan)(x) instead of isnan(x), Clang will compile the former as a direct+-- function call rather than as a macro application. Some experimentation+-- reveals that the isnan function's argument is always a double, so we give its+-- argument the type double here to match this unstated convention. We follow+-- suit similarly with isinf.+--+-- Clang does not yet provide direct function call versions of isfinite() or+-- isnormal(), so we do not provide overrides for them.++llvmIsinfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (BVType 32)+llvmIsinfOverride =+ [llvmOvr| i32 @isinf( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callIsinf (knownNat @32)) args)++-- __isinf and __isinff are like the isinf macro, except their arguments are+-- known to be double or float, respectively. They are not mentioned in the+-- POSIX source standard, only the binary standard. See+-- http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/baselib---isinf.html and+-- http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/baselib---isinff.html.+llvm__isinfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (BVType 32)+llvm__isinfOverride =+ [llvmOvr| i32 @__isinf( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callIsinf (knownNat @32)) args)++llvm__isinffOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (BVType 32)+llvm__isinffOverride =+ [llvmOvr| i32 @__isinff( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callIsinf (knownNat @32)) args)++llvmIsnanOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (BVType 32)+llvmIsnanOverride =+ [llvmOvr| i32 @isnan( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callIsnan (knownNat @32)) args)++-- __isnan and __isnanf are like the isnan macro, except their arguments are+-- known to be double or float, respectively. They are not mentioned in the+-- POSIX source standard, only the binary standard. See+-- http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/baselib---isnan.html and+-- http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/baselib---isnanf.html.+llvm__isnanOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (BVType 32)+llvm__isnanOverride =+ [llvmOvr| i32 @__isnan( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callIsnan (knownNat @32)) args)++llvm__isnanfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (BVType 32)+llvm__isnanfOverride =+ [llvmOvr| i32 @__isnanf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callIsnan (knownNat @32)) args)++-- macOS compiles isnan() to __isnand() when the argument is a double.+llvm__isnandOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (BVType 32)+llvm__isnandOverride =+ [llvmOvr| i32 @__isnand( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callIsnan (knownNat @32)) args)++llvmSqrtOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmSqrtOverride =+ [llvmOvr| double @sqrt( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment callSqrt args)++llvmSqrtfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmSqrtfOverride =+ [llvmOvr| float @sqrtf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment callSqrt args)++callSpecialFunction1 ::+ forall fi p sym ext r args ret.+ (IsSymInterface sym, KnownRepr FloatInfoRepr fi) =>+ W4.SpecialFunction (EmptyCtx ::> W4.R) ->+ RegEntry sym (FloatType fi) ->+ OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))+callSpecialFunction1 fn (regValue -> x) = do+ sym <- getSymInterface+ liftIO $ iFloatSpecialFunction1 sym (knownRepr :: FloatInfoRepr fi) fn x++callSpecialFunction2 ::+ forall fi p sym ext r args ret.+ (IsSymInterface sym, KnownRepr FloatInfoRepr fi) =>+ W4.SpecialFunction (EmptyCtx ::> W4.R ::> W4.R) ->+ RegEntry sym (FloatType fi) ->+ RegEntry sym (FloatType fi) ->+ OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))+callSpecialFunction2 fn (regValue -> x) (regValue -> y) = do+ sym <- getSymInterface+ liftIO $ iFloatSpecialFunction2 sym (knownRepr :: FloatInfoRepr fi) fn x y++callCeil ::+ forall fi p sym ext r args ret.+ IsSymInterface sym =>+ RegEntry sym (FloatType fi) ->+ OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))+callCeil (regValue -> x) = do+ sym <- getSymInterface+ liftIO $ iFloatRound @_ @fi sym RTP x++callFloor ::+ forall fi p sym ext r args ret.+ IsSymInterface sym =>+ RegEntry sym (FloatType fi) ->+ OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))+callFloor (regValue -> x) = do+ sym <- getSymInterface+ liftIO $ iFloatRound @_ @fi sym RTN x++-- | An implementation of @libc@'s @fma@ function.+callFMA ::+ forall fi p sym ext r args ret+ . IsSymInterface sym+ => RegEntry sym (FloatType fi)+ -> RegEntry sym (FloatType fi)+ -> RegEntry sym (FloatType fi)+ -> OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))+callFMA (regValue -> x) (regValue -> y) (regValue -> z) = do+ sym <- getSymInterface+ liftIO $ iFloatFMA @_ @fi sym defaultRM x y z++-- | An implementation of @libc@'s @isinf@ macro. This returns @1@ when the+-- argument is positive infinity, @-1@ when the argument is negative infinity,+-- and zero otherwise.+callIsinf ::+ forall fi w p sym ext r args ret.+ (IsSymInterface sym, 1 <= w) =>+ NatRepr w ->+ RegEntry sym (FloatType fi) ->+ OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callIsinf w (regValue -> x) = do+ sym <- getSymInterface+ liftIO $ do+ isInf <- iFloatIsInf @_ @fi sym x+ isNeg <- iFloatIsNeg @_ @fi sym x+ isPos <- iFloatIsPos @_ @fi sym x+ isInfN <- andPred sym isInf isNeg+ isInfP <- andPred sym isInf isPos+ bv1 <- bvOne sym w+ bvNeg1 <- bvNeg sym bv1+ bv0 <- bvZero sym w+ res0 <- bvIte sym isInfP bv1 bv0+ bvIte sym isInfN bvNeg1 res0++callIsnan ::+ forall fi w p sym ext r args ret.+ (IsSymInterface sym, 1 <= w) =>+ NatRepr w ->+ RegEntry sym (FloatType fi) ->+ OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callIsnan w (regValue -> x) = do+ sym <- getSymInterface+ liftIO $ do+ isnan <- iFloatIsNaN @_ @fi sym x+ bv1 <- bvOne sym w+ bv0 <- bvZero sym w+ -- isnan() is allowed to return any nonzero value if the argument is NaN, and+ -- out of all the possible nonzero values, `1` is certainly one of them.+ bvIte sym isnan bv1 bv0++callSqrt ::+ forall fi p sym ext r args ret.+ IsSymInterface sym =>+ RegEntry sym (FloatType fi) ->+ OverrideSim p sym ext r args ret (RegValue sym (FloatType fi))+callSqrt (regValue -> x) = do+ sym <- getSymInterface+ liftIO $ iFloatSqrt @_ @fi sym defaultRM x++------------------------------------------------------------------------+-- **** Circular trigonometry functions++-- sin(f)++llvmSinOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmSinOverride =+ [llvmOvr| double @sin( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Sin) args)++llvmSinfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmSinfOverride =+ [llvmOvr| float @sinf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Sin) args)++-- cos(f)++llvmCosOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmCosOverride =+ [llvmOvr| double @cos( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Cos) args)++llvmCosfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmCosfOverride =+ [llvmOvr| float @cosf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Cos) args)++-- tan(f)++llvmTanOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmTanOverride =+ [llvmOvr| double @tan( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Tan) args)++llvmTanfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmTanfOverride =+ [llvmOvr| float @tanf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Tan) args)++-- asin(f)++llvmAsinOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmAsinOverride =+ [llvmOvr| double @asin( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arcsin) args)++llvmAsinfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmAsinfOverride =+ [llvmOvr| float @asinf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arcsin) args)++-- acos(f)++llvmAcosOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmAcosOverride =+ [llvmOvr| double @acos( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arccos) args)++llvmAcosfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmAcosfOverride =+ [llvmOvr| float @acosf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arccos) args)++-- atan(f)++llvmAtanOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmAtanOverride =+ [llvmOvr| double @atan( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arctan) args)++llvmAtanfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmAtanfOverride =+ [llvmOvr| float @atanf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arctan) args)++------------------------------------------------------------------------+-- **** Hyperbolic trigonometry functions++-- sinh(f)++llvmSinhOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmSinhOverride =+ [llvmOvr| double @sinh( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Sinh) args)++llvmSinhfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmSinhfOverride =+ [llvmOvr| float @sinhf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Sinh) args)++-- cosh(f)++llvmCoshOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmCoshOverride =+ [llvmOvr| double @cosh( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Cosh) args)++llvmCoshfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmCoshfOverride =+ [llvmOvr| float @coshf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Cosh) args)++-- tanh(f)++llvmTanhOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmTanhOverride =+ [llvmOvr| double @tanh( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Tanh) args)++llvmTanhfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmTanhfOverride =+ [llvmOvr| float @tanhf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Tanh) args)++-- asinh(f)++llvmAsinhOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmAsinhOverride =+ [llvmOvr| double @asinh( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arcsinh) args)++llvmAsinhfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmAsinhfOverride =+ [llvmOvr| float @asinhf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arcsinh) args)++-- acosh(f)++llvmAcoshOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmAcoshOverride =+ [llvmOvr| double @acosh( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arccosh) args)++llvmAcoshfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmAcoshfOverride =+ [llvmOvr| float @acoshf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arccosh) args)++-- atanh(f)++llvmAtanhOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmAtanhOverride =+ [llvmOvr| double @atanh( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arctanh) args)++llvmAtanhfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmAtanhfOverride =+ [llvmOvr| float @atanhf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Arctanh) args)++------------------------------------------------------------------------+-- **** Rectangular to polar coordinate conversion++-- hypot(f)++llvmHypotOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmHypotOverride =+ [llvmOvr| double @hypot( double, double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction2 W4.Hypot) args)++llvmHypotfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmHypotfOverride =+ [llvmOvr| float @hypotf( float, float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction2 W4.Hypot) args)++-- atan2(f)++llvmAtan2Override ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmAtan2Override =+ [llvmOvr| double @atan2( double, double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction2 W4.Arctan2) args)++llvmAtan2fOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmAtan2fOverride =+ [llvmOvr| float @atan2f( float, float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction2 W4.Arctan2) args)++------------------------------------------------------------------------+-- **** Exponential and logarithm functions++-- pow(f)++llvmPowfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmPowfOverride =+ [llvmOvr| float @powf( float, float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction2 W4.Pow) args)++llvmPowOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmPowOverride =+ [llvmOvr| double @pow( double, double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction2 W4.Pow) args)++-- exp(f)++llvmExpOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmExpOverride =+ [llvmOvr| double @exp( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Exp) args)++llvmExpfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmExpfOverride =+ [llvmOvr| float @expf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Exp) args)++-- log(f)++llvmLogOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmLogOverride =+ [llvmOvr| double @log( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Log) args)++llvmLogfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmLogfOverride =+ [llvmOvr| float @logf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Log) args)++-- expm1(f)++llvmExpm1Override ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmExpm1Override =+ [llvmOvr| double @expm1( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Expm1) args)++llvmExpm1fOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmExpm1fOverride =+ [llvmOvr| float @expm1f( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Expm1) args)++-- log1p(f)++llvmLog1pOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmLog1pOverride =+ [llvmOvr| double @log1p( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Log1p) args)++llvmLog1pfOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmLog1pfOverride =+ [llvmOvr| float @log1pf( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Log1p) args)++------------------------------------------------------------------------+-- **** Base 2 exponential and logarithm++-- exp2(f)++llvmExp2Override ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmExp2Override =+ [llvmOvr| double @exp2( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Exp2) args)++llvmExp2fOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmExp2fOverride =+ [llvmOvr| float @exp2f( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Exp2) args)++-- log2(f)++llvmLog2Override ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmLog2Override =+ [llvmOvr| double @log2( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Log2) args)++llvmLog2fOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmLog2fOverride =+ [llvmOvr| float @log2f( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Log2) args)++------------------------------------------------------------------------+-- **** Base 10 exponential and logarithm++-- exp10(f)++llvmExp10Override ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmExp10Override =+ [llvmOvr| double @exp10( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Exp10) args)++llvmExp10fOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmExp10fOverride =+ [llvmOvr| float @exp10f( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Exp10) args)++-- macOS uses __exp10(f) instead of exp10(f).++llvm__exp10Override ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvm__exp10Override =+ [llvmOvr| double @__exp10( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Exp10) args)++llvm__exp10fOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvm__exp10fOverride =+ [llvmOvr| float @__exp10f( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Exp10) args)++-- log10(f)++llvmLog10Override ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType DoubleFloat)+ (FloatType DoubleFloat)+llvmLog10Override =+ [llvmOvr| double @log10( double ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Log10) args)++llvmLog10fOverride ::+ IsSymInterface sym =>+ LLVMOverride p sym ext+ (EmptyCtx ::> FloatType SingleFloat)+ (FloatType SingleFloat)+llvmLog10fOverride =+ [llvmOvr| float @log10f( float ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callSpecialFunction1 W4.Log10) args)++------------------------------------------------------------------------+-- *** Other++-- from OSX libc+llvmAssertRtnOverride+ :: ( IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym+ , ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> LLVMPointerType wptr+ ::> BVType 32+ ::> LLVMPointerType wptr)+ UnitType+llvmAssertRtnOverride =+ [llvmOvr| void @__assert_rtn( i8*, i8*, i32, i8* ) |]+ callAssert++-- From glibc+llvmAssertFailOverride+ :: ( IsSymInterface sym, HasPtrWidth wptr, HasLLVMAnn sym+ , ?intrinsicsOpts :: IntrinsicsOptions, ?memOpts :: MemOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr+ ::> LLVMPointerType wptr+ ::> BVType 32+ ::> LLVMPointerType wptr)+ UnitType+llvmAssertFailOverride =+ [llvmOvr| void @__assert_fail( i8*, i8*, i32, i8* ) |]+ callAssert+++llvmAbortOverride+ :: ( IsSymInterface sym+ , ?intrinsicsOpts :: IntrinsicsOptions )+ => LLVMOverride p sym ext EmptyCtx UnitType+llvmAbortOverride =+ [llvmOvr| void @abort() |]+ (\_ _args ->+ ovrWithBackend $ \bak -> liftIO $ do + let sym = backendGetSym bak+ when (abnormalExitBehavior ?intrinsicsOpts == AlwaysFail) $+ let err = AssertFailureSimError "Call to abort" "" in+ assert bak (falsePred sym) err+ loc <- getCurrentProgramLoc sym+ abortExecBecause $ EarlyExit loc+ )++llvmExitOverride+ :: forall sym p ext+ . ( IsSymInterface sym+ , ?intrinsicsOpts :: IntrinsicsOptions )+ => LLVMOverride p sym ext+ (EmptyCtx ::> BVType 32)+ UnitType+llvmExitOverride =+ [llvmOvr| void @exit( i32 ) |]+ (\_ args -> Ctx.uncurryAssignment callExit args)++llvmGetenvOverride+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr)+ (LLVMPointerType wptr)+llvmGetenvOverride =+ [llvmOvr| i8* @getenv( i8* ) |]+ (\_ _args -> do+ sym <- getSymInterface+ liftIO $ mkNullPointer sym PtrWidth)++llvmHtonlOverride ::+ (IsSymInterface sym, ?lc :: TypeContext) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType 32)+ (BVType 32)+llvmHtonlOverride =+ [llvmOvr| i32 @htonl( i32 ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callBSwapIfLittleEndian (knownNat @4)) args)++llvmHtonsOverride ::+ (IsSymInterface sym, ?lc :: TypeContext) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType 16)+ (BVType 16)+llvmHtonsOverride =+ [llvmOvr| i16 @htons( i16 ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callBSwapIfLittleEndian (knownNat @2)) args)++llvmNtohlOverride ::+ (IsSymInterface sym, ?lc :: TypeContext) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType 32)+ (BVType 32)+llvmNtohlOverride =+ [llvmOvr| i32 @ntohl( i32 ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callBSwapIfLittleEndian (knownNat @4)) args)++llvmNtohsOverride ::+ (IsSymInterface sym, ?lc :: TypeContext) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType 16)+ (BVType 16)+llvmNtohsOverride =+ [llvmOvr| i16 @ntohs( i16 ) |]+ (\_memOps args -> Ctx.uncurryAssignment (callBSwapIfLittleEndian (knownNat @2)) args)++llvmAbsOverride ::+ (IsSymInterface sym, HasLLVMAnn sym) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType 32)+ (BVType 32)+llvmAbsOverride =+ [llvmOvr| i32 @abs( i32 ) |]+ (\mvar args ->+ do callStack <- callStackFromMemVar' mvar+ Ctx.uncurryAssignment (callLibcAbs callStack (knownNat @32)) args)++-- @labs@ uses `long` as its argument and result type, so we need two overrides+-- for @labs@. See Note [Overrides involving (unsigned) long] in+-- Lang.Crucible.LLVM.Intrinsics.+llvmLAbsOverride_32 ::+ (IsSymInterface sym, HasLLVMAnn sym) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType 32)+ (BVType 32)+llvmLAbsOverride_32 =+ [llvmOvr| i32 @labs( i32 ) |]+ (\mvar args ->+ do callStack <- callStackFromMemVar' mvar+ Ctx.uncurryAssignment (callLibcAbs callStack (knownNat @32)) args)++llvmLAbsOverride_64 ::+ (IsSymInterface sym, HasLLVMAnn sym) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType 64)+ (BVType 64)+llvmLAbsOverride_64 =+ [llvmOvr| i64 @labs( i64 ) |]+ (\mvar args ->+ do callStack <- callStackFromMemVar' mvar+ Ctx.uncurryAssignment (callLibcAbs callStack (knownNat @64)) args)++llvmLLAbsOverride ::+ (IsSymInterface sym, HasLLVMAnn sym) =>+ LLVMOverride p sym ext+ (EmptyCtx ::> BVType 64)+ (BVType 64)+llvmLLAbsOverride =+ [llvmOvr| i64 @llabs( i64 ) |]+ (\mvar args ->+ do callStack <- callStackFromMemVar' mvar+ Ctx.uncurryAssignment (callLibcAbs callStack (knownNat @64)) args)++callBSwap ::+ (1 <= width, IsSymInterface sym) =>+ NatRepr width ->+ RegEntry sym (BVType (width * 8)) ->+ OverrideSim p sym ext r args ret (RegValue sym (BVType (width * 8)))+callBSwap widthRepr (regValue -> vec) = do+ sym <- getSymInterface+ liftIO $ bvSwap sym widthRepr vec++-- | This determines under what circumstances @callAbs@ should check if its+-- argument is equal to the smallest signed integer of a particular size+-- (e.g., @INT_MIN@), and if it is equal to that value, what kind of error+-- should be reported.+data CheckAbsIntMin+ = LibcAbsIntMinUB+ -- ^ For the @abs@, @labs@, and @llabs@ functions, always check if the+ -- argument is equal to @INT_MIN@. If so, report it as undefined+ -- behavior per the C standard.+ | LLVMAbsIntMinPoison Bool+ -- ^ For the @llvm.abs.*@ family of LLVM intrinsics, check if the argument+ -- is equal to @INT_MIN@ only when the 'Bool' argument is 'True'. If it+ -- is 'True' and the argument is equal to @INT_MIN@, return poison.++-- | The workhorse for the @abs@, @labs@, and @llabs@ functions, as well as the+-- @llvm.abs.*@ family of overloaded intrinsics.+callAbs ::+ forall w p sym ext r args ret.+ (1 <= w, IsSymInterface sym, HasLLVMAnn sym) =>+ CallStack ->+ CheckAbsIntMin ->+ NatRepr w ->+ RegEntry sym (BVType w) ->+ OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callAbs callStack checkIntMin widthRepr (regValue -> src) = do+ sym <- getSymInterface+ ovrWithBackend $ \bak -> liftIO $ do+ bvIntMin <- bvLit sym widthRepr (BV.minSigned widthRepr)+ isNotIntMin <- notPred sym =<< bvEq sym src bvIntMin++ when shouldCheckIntMin $ do+ isNotIntMinUB <- annotateUB sym callStack ub isNotIntMin+ let err = AssertFailureSimError "Undefined behavior encountered" $+ show $ UB.explain ub+ assert bak isNotIntMinUB err++ isSrcNegative <- bvIsNeg sym src+ srcNegated <- bvNeg sym src+ bvIte sym isSrcNegative srcNegated src+ where+ shouldCheckIntMin :: Bool+ shouldCheckIntMin =+ case checkIntMin of+ LibcAbsIntMinUB -> True+ LLVMAbsIntMinPoison shouldCheck -> shouldCheck++ ub :: UB.UndefinedBehavior (RegValue' sym)+ ub = case checkIntMin of+ LibcAbsIntMinUB ->+ UB.AbsIntMin $ RV src+ LLVMAbsIntMinPoison{} ->+ UB.PoisonValueCreated $ Poison.LLVMAbsIntMin $ RV src++callLibcAbs ::+ (1 <= w, IsSymInterface sym, HasLLVMAnn sym) =>+ CallStack ->+ NatRepr w ->+ RegEntry sym (BVType w) ->+ OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callLibcAbs callStack = callAbs callStack LibcAbsIntMinUB++callLLVMAbs ::+ (1 <= w, IsSymInterface sym, HasLLVMAnn sym) =>+ CallStack ->+ NatRepr w ->+ RegEntry sym (BVType w) ->+ RegEntry sym (BVType 1) ->+ OverrideSim p sym ext r args ret (RegValue sym (BVType w))+callLLVMAbs callStack widthRepr src (regValue -> isIntMinPoison) = do+ shouldCheckIntMin <- liftIO $+ -- Per https://releases.llvm.org/12.0.0/docs/LangRef.html#id451, the second+ -- argument must be a constant.+ case asBV isIntMinPoison of+ Just bv -> pure (bv /= BV.zero (knownNat @1))+ Nothing -> malformedLLVMModule+ "Call to llvm.abs.* with non-constant second argument"+ [printSymExpr isIntMinPoison]+ callAbs callStack (LLVMAbsIntMinPoison shouldCheckIntMin) widthRepr src++-- | If the data layout is little-endian, run 'callBSwap' on the input.+-- Otherwise, return the input unchanged. This is the workhorse for the+-- @hton{s,l}@ and @ntoh{s,l}@ overrides.+callBSwapIfLittleEndian ::+ (1 <= width, IsSymInterface sym, ?lc :: TypeContext) =>+ NatRepr width ->+ RegEntry sym (BVType (width * 8)) ->+ OverrideSim p sym ext r args ret (RegValue sym (BVType (width * 8)))+callBSwapIfLittleEndian widthRepr vec =+ case (llvmDataLayout ?lc)^.intLayout of+ BigEndian -> pure (regValue vec)+ LittleEndian -> callBSwap widthRepr vec++----------------------------------------------------------------------------+-- atexit stuff++cxa_atexitOverride+ :: (IsSymInterface sym, HasPtrWidth wptr)+ => LLVMOverride p sym ext+ (EmptyCtx ::> LLVMPointerType wptr ::> LLVMPointerType wptr ::> LLVMPointerType wptr)+ (BVType 32)+cxa_atexitOverride =+ [llvmOvr| i32 @__cxa_atexit( void (i8*)*, i8*, i8* ) |]+ (\_ _args -> do+ sym <- getSymInterface+ liftIO $ bvZero sym knownNat) ----------------------------------------------------------------------------
src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs view
@@ -35,7 +35,6 @@ ) where import qualified ABI.Itanium as ABI-import Control.Applicative (empty) import Control.Lens ((^.)) import Control.Monad.Reader import Data.List (isInfixOf)@@ -50,12 +49,14 @@ import Lang.Crucible.Backend import Lang.Crucible.CFG.Common (GlobalVar)+import Lang.Crucible.Simulator.OverrideSim (getSymInterface) 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 qualified Lang.Crucible.LLVM.Intrinsics.Match as Match import Lang.Crucible.LLVM.MemModel import Lang.Crucible.LLVM.Translation.Monad import Lang.Crucible.LLVM.Translation.Types@@ -68,16 +69,12 @@ register_cpp_override :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => SomeCPPOverride p sym arch ->- OverrideTemplate p sym arch rtp l a+ OverrideTemplate p sym LLVM arch register_cpp_override someCPPOverride =- OverrideTemplate (SubstringsMatch ("_Z" : cppOverrideSubstrings someCPPOverride)) $- do (requestedDecl, decName, llvmctx) <- ask- case decName of- Nothing -> empty- Just nm ->- case cppOverrideAction someCPPOverride requestedDecl nm llvmctx of- Nothing -> empty- Just (SomeLLVMOverride override) -> register_llvm_override override+ OverrideTemplate (Match.SubstringsMatch ("_Z" : cppOverrideSubstrings someCPPOverride)) $+ MakeOverride $ \requestedDecl decName llvmctx -> do+ nm <- decName+ cppOverrideAction someCPPOverride requestedDecl nm llvmctx -- type CPPOverride p sym arch args ret =@@ -89,7 +86,7 @@ data SomeCPPOverride p sym arch = SomeCPPOverride { cppOverrideSubstrings :: [String]- , cppOverrideAction :: L.Declare -> ABI.DecodedName -> LLVMContext arch -> Maybe (SomeLLVMOverride p sym)+ , cppOverrideAction :: L.Declare -> ABI.DecodedName -> LLVMContext arch -> Maybe (SomeLLVMOverride p sym LLVM) } ------------------------------------------------------------------------@@ -126,7 +123,7 @@ -- 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))+ -> (forall args ret. L.Declare -> CtxRepr args -> TypeRepr ret -> Maybe (SomeLLVMOverride p sym LLVM)) -> (L.Symbol -> ABI.DecodedName -> Bool) -> SomeCPPOverride p sym arch mkOverride substrings ov filt =@@ -147,7 +144,7 @@ voidOverride substrings = mkOverride substrings $ \decl argTys retTy -> Just $ case retTy of- UnitRepr -> SomeLLVMOverride $ LLVMOverride decl argTys retTy $ \_mem _sym _args -> pure ()+ UnitRepr -> SomeLLVMOverride $ LLVMOverride decl argTys retTy $ \_mem _args -> pure () _ -> panic_ "voidOverride" decl argTys retTy -- | Make an override for a function of (LLVM) type @a -> a@, for any @a@.@@ -162,7 +159,7 @@ case argTys of (Ctx.Empty Ctx.:> argTy) | Just Refl <- testEquality argTy retTy ->- SomeLLVMOverride $ LLVMOverride decl argTys retTy $ \_mem _sym args ->+ SomeLLVMOverride $ LLVMOverride decl argTys retTy $ \_mem args -> -- Just return the input pure (Ctx.uncurryAssignment regValue args) @@ -180,7 +177,7 @@ case argTys of (Ctx.Empty Ctx.:> fstTy Ctx.:> _) | Just Refl <- testEquality fstTy retTy ->- SomeLLVMOverride $ LLVMOverride decl argTys retTy $ \_mem _sym args ->+ SomeLLVMOverride $ LLVMOverride decl argTys retTy $ \_mem args -> pure (Ctx.uncurryAssignment (const . regValue) args) _ -> panic_ "constOverride" decl argTys retTy@@ -196,8 +193,9 @@ mkOverride substrings $ \decl argTys retTy -> Just $ case testEquality retTy ty of Just Refl ->- SomeLLVMOverride $ LLVMOverride decl argTys retTy $ \mem bak _args ->- liftIO (regval mem (backendGetSym bak))+ SomeLLVMOverride $ LLVMOverride decl argTys retTy $ \mem _args -> do+ sym <- getSymInterface+ liftIO (regval mem sym) _ -> panic_ "fixedOverride" decl argTys retTy
+ src/Lang/Crucible/LLVM/Intrinsics/Match.hs view
@@ -0,0 +1,109 @@+-- |+-- Module : Lang.Crucible.LLVM.Intrinsics.Match+-- Description : Matching overrides to function names+-- Copyright : (c) Galois, Inc 2024+-- License : BSD3+-- Maintainer : Langston Barrett <langston@galois.com>+-- Stability : provisional+------------------------------------------------------------------------++module Lang.Crucible.LLVM.Intrinsics.Match+ ( TemplateMatcher(..)+ , matches+ , stripDarwinAliases+ ) where++import Control.Applicative (asum)+import qualified Data.List as List+import qualified Data.List.Extra as List (stripInfix)+import Data.Maybe (fromMaybe)++-- | This type controls whether an override is installed for a given name found in a module.+-- See 'Lang.Crucible.LLVM.Intrinsics.filterTemplates'.+data TemplateMatcher+ = ExactMatch String+ | PrefixMatch String+ | SubstringsMatch [String]+ | DarwinAliasMatch String+ -- ^ Match a name up to some number of Darwin aliases.+ -- See @Note [Darwin aliases]@.++-- | Check whether a 'TemplateMatcher' matches a given function name.+matches ::+ -- | Function name+ String ->+ TemplateMatcher ->+ Bool+matches nm (ExactMatch x) = x == nm+matches nm (PrefixMatch pfx) = pfx `List.isPrefixOf` nm+matches nm (DarwinAliasMatch x) = x == stripDarwinAliases nm+matches nm (SubstringsMatch subs) = filterSubstrings subs nm+ where+ filterSubstrings [] _ = True+ filterSubstrings (a:as) xs =+ case restAfterSubstring a xs of+ Nothing -> False+ Just rest -> filterSubstrings as rest++ restAfterSubstring :: String -> String -> Maybe String+ restAfterSubstring sub xs = asum [ List.stripPrefix sub tl | tl <- List.tails xs ]+++-- | Remove all prefixes and suffixes that might occur in a Darwin alias for+-- a function name. See @Note [Darwin aliases]@.+stripDarwinAliases :: String -> String+stripDarwinAliases str =+ -- Remove the \01_ prefix, if it exists...+ let strNoPrefix = fromMaybe str (List.stripPrefix "\01_" str) in+ -- ...and remove any suffixes as well. Because there can be multiple suffixes+ -- in an alias, we use `stripInfix` in case one of the prefixes does not+ -- appear at the very end of the name.+ foldr (\suf s ->+ case List.stripInfix suf s of+ Just (before, after) -> before ++ after+ Nothing -> s)+ strNoPrefix+ suffixes+ where+ suffixes :: [String]+ suffixes = [ "$UNIX2003"+ , "$INODE64"+ , "$1050"+ , "$NOCANCEL"+ , "$DARWIN_EXTSN"+ ]++{-+Note [Darwin aliases]+~~~~~~~~~~~~~~~~~~~~~+Operating systems derived from Darwin, such as macOS, define several aliases+for common libc functions for versioning purposes. These aliases are defined+using __asm, so when Clang compiles these aliases, the name that appears in the+resulting bitcode will look slightly different from what appears in the source+C file. For example, compiling the write() function with Clang on macOS will+produce LLVM bitcode with the name \01_write(), where \01 represents a leading+ASCII character with code 0x01.++Aside from the \01_ prefix, there also a number of suffixes that can be used+in alias names (see `stripDarwinAliases` for the complete list). There are+enough possible combinations that it is not wise to try and write them all out+by hand. Instead, we take the approach that when using crucible-llvm on Darwin,+we treat any C function as possibly containing Darwin aliases. That is:++* In `basic_llvm_override`, we use a special DarwinAliasMatch template matcher+ on Darwin. When matching against possible overrides, DarwinAliasMatch+ indicates that function should be match the underlying name after removing+ any possible Darwin-related prefixes or suffixes (see the+ `stripDarwinAliases` function, which implements this).+* If a function name in a program matches an override name after stripping+ Darwin aliases, then we proceed to use the override, but with the override's+ name switched out for the name of the function from the program. This way,+ we write overrides for the "normalized" name (e.g., write) but have them work+ seamlessly for aliases names (e.g., \01_write) as well.++Currently, we only apply this special treatment in `basic_llvm_override`, as+we have only observed the aliases being used on libc functions. We may need to+apply this special case to other override functions (e.g.,+`register_cpp_override`) if that proves insufficient.+-}+
src/Lang/Crucible/LLVM/Intrinsics/Options.hs view
@@ -20,9 +20,9 @@ -- ^ Functions which trigger an abnormal exit will always cause Crucible -- to fail. | OnlyAssertFail- -- ^ The @__assert_fail()@ function will cause Crucible to fail, while- -- other functions which triggern an abnormal exit will not cause- -- failures. This option is primarily useful for SV-COMP.+ -- ^ The @__assert_fail()@ or @__assert_rtn()@ functions will cause Crucible+ -- to fail, while other functions which trigger an abnormal exit will not+ -- cause failures. This option is primarily useful for SV-COMP. | NeverFail -- ^ Functions which trigger an abnormal exit will never cause Crucible -- to fail. This option is primarily useful for SV-COMP.
src/Lang/Crucible/LLVM/MemModel.hs view
@@ -59,6 +59,7 @@ , G.ppPtr , G.ppTermExpr , llvmPointer_bv+ , Partial.ptrToBv , Partial.projectLLVM_bv -- * Memory operations@@ -66,7 +67,6 @@ , doMallocUnbounded , G.AllocType(..) , G.Mutability(..)- , doMallocHandle , ME.FuncLookupError(..) , ME.ppFuncLookupError , doLookupHandle@@ -87,7 +87,6 @@ , loadMaybeString , strLen , uncheckedMemcpy- , bindLLVMFunPtr -- * \"Raw\" operations with LLVMVal , LLVMVal(..)@@ -96,6 +95,7 @@ , unpackMemValue , packMemValue , loadRaw+ , loadArrayConcreteSizeRaw , storeRaw , condStoreRaw , storeConstRaw@@ -163,6 +163,7 @@ , G.pushStackFrameMem , G.popStackFrameMem , G.asMemAllocationArrayStore+ , G.asMemMatchingArrayStore , SomeFnHandle(..) , G.SomeAlloc(..) , G.possibleAllocs@@ -214,6 +215,7 @@ import What4.Interface import What4.Expr( GroundValue )+import qualified What4.Expr.ArrayUpdateMap as AUM import What4.InterpretedFloatingPoint import What4.ProgramLoc @@ -422,7 +424,7 @@ eval (LLVM_MemClear mvar (regValue -> ptr) bytes) = do mem <- getMem mvar- z <- liftIO $ bvLit sym knownNat (BV.zero knownNat)+ z <- liftIO $ bvZero sym knownNat len <- liftIO $ bvLit sym PtrWidth (bytesToBV PtrWidth bytes) mem' <- liftIO $ doMemset bak PtrWidth mem ptr z len setMem mvar mem'@@ -562,7 +564,7 @@ let sym = backendGetSym bak blkNum <- liftIO $ nextBlock (memImplBlockSource mem) blk <- liftIO $ natLit sym blkNum- z <- liftIO $ bvLit sym PtrWidth (BV.zero PtrWidth)+ z <- liftIO $ bvZero sym PtrWidth let heap' = G.allocMem G.StackAlloc blkNum (Just sz) alignment G.Mutable loc (memImplHeap mem) let ptr = LLVMPointer blk z@@ -624,22 +626,6 @@ SomeFnHandle :: FnHandle args ret -> SomeFnHandle VarargsFnHandle :: FnHandle (args ::> VectorType AnyType) ret -> SomeFnHandle -sextendBVTo :: (1 <= w, 1 <= w', IsSymInterface sym)- => sym- -> NatRepr w- -> NatRepr w'- -> SymExpr sym (BaseBVType w)- -> IO (SymExpr sym (BaseBVType w'))-sextendBVTo sym w w' x- | Just Refl <- testEquality w w' = return x- | Just LeqProof <- testLeq (incNat w) w' = bvSext sym w' x- | Just LeqProof <- testLeq (incNat w') w = bvTrunc sym w' x- | otherwise = panic "sextendBVTo"- [ "Impossible widths!"- , show w- , show w'- ]- -- | Allocate and zero a memory region with /size * number/ bytes. -- -- Precondition: the multiplication /size * number/ does not overflow.@@ -662,7 +648,7 @@ loc <- plSourceLoc <$> getCurrentProgramLoc sym let displayString = "<calloc> " ++ show loc- z <- bvLit sym knownNat (BV.zero knownNat)+ z <- bvZero sym knownNat (ptr, mem') <- doMalloc bak G.HeapAlloc G.Mutable displayString mem sz' alignment mem'' <- doMemset bak PtrWidth mem' ptr z sz' return (ptr, mem'')@@ -709,7 +695,7 @@ let sym = backendGetSym bak blkNum <- nextBlock (memImplBlockSource mem) blk <- natLit sym blkNum- z <- bvLit sym PtrWidth (BV.zero PtrWidth)+ z <- bvZero sym PtrWidth let heap' = G.allocMem allocType blkNum sz alignment mut loc (memImplHeap mem) let ptr = LLVMPointer blk z let mem' = mem{ memImplHeap = heap' }@@ -720,25 +706,12 @@ else pure mem' return (ptr, mem'') ---bindLLVMFunPtr ::- (IsSymBackend sym bak, HasPtrWidth wptr) =>- bak ->- L.Symbol ->- FnHandle args ret ->- MemImpl sym ->- IO (MemImpl sym)-bindLLVMFunPtr bak nm h mem- | (_ Ctx.:> VectorRepr AnyRepr) <- handleArgTypes h-- = do ptr <- doResolveGlobal bak mem nm- doInstallHandle bak ptr (VarargsFnHandle h) mem-- | otherwise- = do ptr <- doResolveGlobal bak mem nm- doInstallHandle bak ptr (SomeFnHandle h) mem-+-- | Associate a function handle with an existing allocation.+--+-- This can overwrite existing allocation/handle associations, and is used to do+-- so when registering lazily-translated CFGs.+--+-- See also "Lang.Crucible.LLVM.Functions". doInstallHandle :: (Typeable a, IsSymBackend sym bak) => bak@@ -757,25 +730,6 @@ , " " ++ show (ppPtr ptr) ] --- | Allocate a memory region for the given handle.-doMallocHandle- :: (Typeable a, IsSymInterface sym, HasPtrWidth wptr)- => sym- -> G.AllocType {- ^ stack, heap, or global -}- -> String {- ^ source location for use in error messages -}- -> MemImpl sym- -> a {- ^ handle -}- -> IO (LLVMPtr sym wptr, MemImpl sym)-doMallocHandle sym allocType loc mem x = do- blkNum <- nextBlock (memImplBlockSource mem)- blk <- natLit sym blkNum- z <- bvLit sym PtrWidth (BV.zero PtrWidth)-- let heap' = G.allocMem allocType blkNum (Just z) noAlignment G.Immutable loc (memImplHeap mem)- let hMap' = Map.insert blkNum (toDyn x) (memImplHandleMap mem)- let ptr = LLVMPointer blk z- return (ptr, mem{ memImplHeap = heap', memImplHandleMap = hMap' })- -- | Look up the handle associated with the given pointer, if any. doLookupHandle :: (Typeable a, IsSymInterface sym)@@ -1069,9 +1023,9 @@ LLVMPtr sym wptr {- ^ base pointer -} -> SymBV sym wptr {- ^ offset -} -> IO (LLVMPtr sym wptr)-doPtrAddOffset bak m x@(LLVMPointer blk _) off = do+doPtrAddOffset bak m x off = do let sym = backendGetSym bak- isBV <- natEq sym blk =<< natLit sym 0+ isBV <- ptrIsBv sym x x' <- ptrAdd sym PtrWidth x off v <- case asConstantPred isBV of Just True -> return isBV@@ -1177,16 +1131,17 @@ Partial.Err pe -> do ast <- impliesPred sym cond pe assert bak ast $ AssertFailureSimError "Error during memory load: strlen" ""- bvLit sym PtrWidth (BV.zero PtrWidth) -- bogus value, but have to return something...+ bvZero sym PtrWidth -- bogus value, but have to return something... Partial.NoErr loadok llvmval -> do ast <- impliesPred sym cond loadok assert bak ast $ AssertFailureSimError "Error during memory load: strlen" "" v <- unpackMemValue sym (LLVMPointerRepr (knownNat @8)) llvmval- test <- bvIsNonzero sym =<< Partial.projectLLVM_bv bak v+ let err = AssertFailureSimError "Found pointer instead of byte in string passed to `strlen`" ""+ test <- bvIsNonzero sym =<< Partial.ptrToBv bak err v iteM bvIte sym test (do cond' <- andPred sym cond test- p' <- doPtrAddOffset bak mem p =<< bvLit sym PtrWidth (BV.one PtrWidth)+ p' <- doPtrAddOffset bak mem p =<< bvOne sym PtrWidth case BV.succUnsigned PtrWidth n of Just n_1 -> go n_1 cond' p' Nothing -> panic "Lang.Crucible.LLVM.MemModel.strLen" ["string length exceeds pointer width"])@@ -1217,12 +1172,13 @@ go f _ (Just 0) = return $ f [] go f p maxChars = do v <- doLoad bak mem p (bitvectorType 1) (LLVMPointerRepr (knownNat :: NatRepr 8)) noAlignment- x <- Partial.projectLLVM_bv bak v+ let err = AssertFailureSimError "Found pointer instead of byte when loading string" ""+ x <- Partial.ptrToBv bak err v case BV.asUnsigned <$> asBV x of Just 0 -> return $ f [] Just c -> do let c' :: Word8 = toEnum $ fromInteger c- p' <- doPtrAddOffset bak mem p =<< bvLit sym PtrWidth (BV.one PtrWidth)+ p' <- doPtrAddOffset bak mem p =<< bvOne sym PtrWidth go (f . (c':)) p' (fmap (\n -> n - 1) maxChars) Nothing -> addFailedAssertion bak@@ -1287,6 +1243,40 @@ let gsym = unsymbol <$> isGlobalPointer (memImplSymbolMap mem) ptr G.readMem sym PtrWidth gsym ptr valType alignment (memImplHeap mem) +-- | Load an array with concrete size from memory.+loadArrayConcreteSizeRaw ::+ forall sym wptr .+ (IsSymInterface sym, HasPtrWidth wptr, Partial.HasLLVMAnn sym, ?memOpts :: MemOptions) =>+ sym ->+ MemImpl sym ->+ LLVMPtr sym wptr ->+ Natural ->+ Alignment ->+ IO (Either (Pred sym) (Pred sym, SymArray sym (SingleCtx (BaseBVType wptr)) (BaseBVType 8)))+loadArrayConcreteSizeRaw sym mem ptr sz alignment+ | sz == 0 = do+ zero_bv <- bvZero sym knownNat+ zero_arr <- constantArray sym (Ctx.singleton $ BaseBVRepr PtrWidth) zero_bv+ return $ Right (truePred sym, zero_arr)+ | otherwise = do+ let gsym = unsymbol <$> isGlobalPointer (memImplSymbolMap mem) ptr+ res <- G.readMem sym PtrWidth gsym ptr (arrayType sz $ bitvectorType 1) alignment (memImplHeap mem)+ case res of+ Partial.NoErr ok llvm_val_arr -> do+ case llvm_val_arr of+ LLVMValArray _ llvm_vals -> do+ let aum = AUM.fromAscList knownRepr $ V.toList $ V.imap+ (\i -> \case+ LLVMValInt _ byte | Just Refl <- testEquality (knownNat @8) (bvWidth byte) ->+ (Ctx.singleton $ BVIndexLit PtrWidth $ BV.mkBV PtrWidth $ fromIntegral i, byte)+ _ -> panic "MemModel.loadArrayRaw" ["expected LLVMValInt"])+ llvm_vals+ zero_bv <- bvZero sym knownNat+ arr <- arrayFromMap sym (Ctx.singleton $ BaseBVRepr PtrWidth) aum zero_bv+ return $ Right (ok, arr)+ _ -> panic "MemModel.loadArrayRaw" ["expected LLVMValArray"]+ Partial.Err err -> return $ Left err+ -- | Store an LLVM value in memory. Asserts that the pointer is valid and points -- to a mutable memory region. storeRaw ::@@ -1662,13 +1652,13 @@ SymBV sym w {- ^ length of region 2 -} -> IO (Pred sym) buildDisjointRegionsAssertion sym w dest dlen src slen = do- let LLVMPointer dblk doff = dest- let LLVMPointer sblk soff = src+ let LLVMPointer _dblk doff = dest+ let LLVMPointer _sblk soff = src dend <- bvAdd sym doff =<< sextendBVTo sym w PtrWidth dlen send <- bvAdd sym soff =<< sextendBVTo sym w PtrWidth slen - diffBlk <- notPred sym =<< natEq sym dblk sblk+ diffBlk <- notPred sym =<< ptrSameAlloc sym dest src destfirst <- bvSle sym dend soff srcfirst <- bvSle sym send doff @@ -1688,15 +1678,15 @@ SymBV sym wptr {- ^ length of region 2 -} -> IO (Pred sym) buildDisjointRegionsAssertionWithSub sym dest dlen src slen = do- let LLVMPointer dblk doff = dest- let LLVMPointer sblk soff = src+ let LLVMPointer _dblk doff = dest+ let LLVMPointer _sblk soff = src dend <- bvAdd sym doff dlen send <- bvAdd sym soff slen - zero_bv <- bvLit sym PtrWidth $ BV.zero PtrWidth+ zero_bv <- bvZero sym PtrWidth - diffBlk <- notPred sym =<< natEq sym dblk sblk+ diffBlk <- notPred sym =<< ptrSameAlloc sym dest src allPos <- andAllOf sym folded =<< mapM (bvSle sym zero_bv) [doff, dend, soff, send] destfirst <- bvSle sym zero_bv =<< bvSub sym soff dend
src/Lang/Crucible/LLVM/MemModel/Generic.hs view
@@ -58,6 +58,7 @@ , branchAbortMem , mergeMem , asMemAllocationArrayStore+ , asMemMatchingArrayStore , isAligned , SomeAlloc(..)@@ -78,6 +79,7 @@ import Control.Lens import Control.Monad import Control.Monad.State.Strict+import Control.Monad.Trans.Maybe import Data.IORef import Data.Maybe import qualified Data.List as List@@ -90,6 +92,7 @@ import Prettyprinter import Lang.Crucible.Panic (panic) +import Data.BitVector.Sized (BV) import qualified Data.BitVector.Sized as BV import Data.Parameterized.Classes import qualified Data.Parameterized.Context as Ctx@@ -790,7 +793,9 @@ else do -- We're playing a trick here. By making a fresh constant a proof obligation, we can be -- sure it always fails. But, because it's a variable, it won't be constant-folded away -- and we can be relatively sure the annotation will survive.- b <- freshConstant sym (safeSymbol "noSatisfyingWrite") BaseBoolRepr+ b <- if noSatisfyingWriteFreshConstant ?memOpts+ then freshConstant sym (safeSymbol "noSatisfyingWrite") BaseBoolRepr+ else return $ falsePred sym Partial.Err <$> Partial.annotateME sym mop (NoSatisfyingWrite tp) b @@ -1037,13 +1042,13 @@ case sz of Nothing -> -- Unbounded access of an unbounded allocation must start at offset 0.- bvEq sym off =<< bvLit sym w (BV.zero w)+ bvEq sym off =<< bvZero sym w Just currSize -> -- Bounded access of an unbounded allocation requires that -- @offset + size <= 2^w@, or equivalently @offset <= 2^w - -- size@. Note that @bvNeg sym size@ computes @2^w - size@ -- for any nonzero @size@.- do zeroSize <- bvEq sym currSize =<< bvLit sym w (BV.zero w)+ do zeroSize <- bvEq sym currSize =<< bvZero sym w noWrap <- bvUle sym off =<< bvNeg sym currSize orPred sym zeroSize noWrap @@ -1145,7 +1150,7 @@ , Just LeqProof <- isPosNat bits , Just LeqProof <- testLeq bits w = do lowbits <- bvSelect sym (knownNat :: NatRepr 0) bits offset- bvEq sym lowbits =<< bvLit sym bits (BV.zero bits)+ bvEq sym lowbits =<< bvZero sym bits isAligned sym _ _ _ = return (falsePred sym) @@ -1314,7 +1319,7 @@ arrayUpdate sym acc_arr (Ctx.singleton idx) byte Partial.NoErr _ (LLVMValZero _) -> do- byte <- bvLit sym knownRepr (BV.zero knownRepr)+ byte <- bvZero sym knownRepr idx <- bvAdd sym (llvmPointerOffset ptr) =<< bvLit sym w (bytesToBV w off) arrayUpdate sym acc_arr (Ctx.singleton idx) byte@@ -1449,7 +1454,7 @@ _ -> return default_m - return (m', p1, p2)+ return (memInsertArrayBlock (llvmPointerBlock ptr) m', p1, p2) -- | Write an array to memory. --@@ -1521,7 +1526,7 @@ allocAndWriteMem sym w a b tp alignment mut loc v m = do sz <- bvLit sym w (bytesToBV w (typeEnd 0 tp)) base <- natLit sym b- off <- bvLit sym w (BV.zero w)+ off <- bvZero sym w let p = LLVMPointer base off return (m & allocMem a b (Just sz) alignment mut loc & memAddWrite p (MemStore v tp alignment))@@ -1570,7 +1575,7 @@ String {- ^ Source location -} -> IO (Mem sym, Pred sym, Pred sym, Pred sym) freeMem sym w (LLVMPointer blk off) m loc =- do p1 <- bvEq sym off =<< bvLit sym w (BV.zero w)+ do p1 <- bvEq sym off =<< bvZero sym w (wasAllocated, notFreed) <- isAllocatedGeneric sym isHeapMutable blk (memAllocs m) return (memAddAlloc (freeMemAllocs blk loc) m, p1, wasAllocated, notFreed) where@@ -1629,6 +1634,22 @@ Just (AllocInfo atp sz mut alignment loc) -> [SomeAlloc atp n sz mut alignment loc] +-- | 'IO' plus memoization. The 'IORef' stores suspended computations with+-- 'Left' and evaluated results with 'Right'.+newtype MemoIO m a = MemoIO (IORef (Either (m a) a))++putMemoIO :: MonadIO m => m a -> m (MemoIO m a)+putMemoIO comp = MemoIO <$> liftIO (newIORef $ Left comp)++getMemoIO :: MonadIO m => MemoIO m a -> m a+getMemoIO (MemoIO ref) = liftIO (readIORef ref) >>= \case+ Left comp -> do+ res <- comp+ liftIO $ writeIORef ref $ Right res+ return res+ Right res -> return res++ -- | Check if @LLVMPtr sym w@ points inside an allocation that is backed -- by an SMT array store. If true, return a predicate that indicates -- when the given array backs the given pointer, the SMT array,@@ -1649,75 +1670,134 @@ IO (Maybe (Pred sym, SymArray sym (SingleCtx (BaseBVType w)) (BaseBVType 8), (SymBV sym w))) asMemAllocationArrayStore sym w ptr mem | Just blk_no <- asNat (llvmPointerBlock ptr)+ , memMemberArrayBlock (llvmPointerBlock ptr) mem , [SomeAlloc _ _ (Just sz) _ _ _] <- List.nub (possibleAllocs blk_no mem) , Just Refl <- testEquality w (bvWidth sz) =- do result <- findArrayStore blk_no sz $ memWritesAtConstant blk_no $ memWrites mem+ do memo_nothing <- putMemoIO $ return Nothing+ --putStrLn $ "asMemAllocationArrayStore: base=" ++ show blk_no ++ " sz=" ++ show (printSymExpr sz)+ result <- findArrayStore sym w blk_no (BV.zero w) sz memo_nothing $+ memWritesAtConstant blk_no $ memWrites mem return $ case result of Just (ok, arr) -> Just (ok, arr, sz) Nothing -> Nothing | otherwise = return Nothing - where- findArrayStore ::- Natural ->- SymBV sym w ->- [MemWrite sym] ->- IO (Maybe (Pred sym, SymArray sym (SingleCtx (BaseBVType w)) (BaseBVType 8)))+asMemMatchingArrayStore ::+ (IsSymInterface sym, 1 <= w) =>+ sym ->+ NatRepr w ->+ LLVMPtr sym w ->+ SymBV sym w ->+ Mem sym ->+ IO (Maybe (Pred sym, SymArray sym (SingleCtx (BaseBVType w)) (BaseBVType 8)))+asMemMatchingArrayStore sym w ptr sz mem+ | Just blk_no <- asNat (llvmPointerBlock ptr)+ , memMemberArrayBlock (llvmPointerBlock ptr) mem+ , Just off <- asBV (llvmPointerOffset ptr) = do+ --putStrLn $ "asMemMatchingArrayStore: ptr=" ++ show (blk_no, off) ++ " sz=" ++ show (printSymExpr sz)+ memo_nothing <- putMemoIO $ return Nothing+ findArrayStore sym w blk_no off sz memo_nothing $ memWritesAtConstant blk_no $ memWrites mem+ | otherwise = return Nothing - findArrayStore _ _ [] = return Nothing+findArrayStore ::+ (IsSymInterface sym, 1 <= w) =>+ sym ->+ NatRepr w ->+ Natural ->+ BV w ->+ SymBV sym w ->+ MemoIO IO (Maybe (Pred sym, SymArray sym (SingleCtx (BaseBVType w)) (BaseBVType 8))) ->+ [MemWrite sym] ->+ IO (Maybe (Pred sym, SymArray sym (SingleCtx (BaseBVType w)) (BaseBVType 8)))+findArrayStore sym w blk_no off sz memo_cont = \case+ [] -> getMemoIO memo_cont+ head_mem_write : tail_mem_writes -> do+ --putStrLn $ " findArrayStore: ptr=" ++ show (blk_no, off) ++ " sz=" ++ show (printSymExpr sz)+ --putStrLn $ " findArrayStore: write=" ++ (case head_mem_write of MemWrite{} -> "write"; WriteMerge{} -> "merge") - findArrayStore blk_no sz (head_mem_write : tail_mem_writes) =- case head_mem_write of- MemWrite write_ptr write_source- | Just write_blk_no <- asNat (llvmPointerBlock write_ptr)- , blk_no == write_blk_no- , Just (BV.BV 0) <- asBV (llvmPointerOffset write_ptr)- , MemArrayStore arr (Just arr_store_sz) <- write_source- , Just Refl <- testEquality w (ptrWidth write_ptr) -> do- ok <- bvEq sym sz arr_store_sz- return (Just (ok, arr))+ case head_mem_write of+ MemWrite write_ptr write_source+ | Just write_blk_no <- asNat (llvmPointerBlock write_ptr)+ , blk_no == write_blk_no+ , Just Refl <- testEquality w (ptrWidth write_ptr)+ , Just write_off <- asBV (llvmPointerOffset write_ptr)+ , off == write_off+ , MemArrayStore arr (Just arr_store_sz) <- write_source -> do+ ok <- bvEq sym sz arr_store_sz+ return (Just (ok, arr)) - | Just write_blk_no <- asNat (llvmPointerBlock write_ptr)- , blk_no /= write_blk_no ->- findArrayStore blk_no sz tail_mem_writes+ | Just write_blk_no <- asNat (llvmPointerBlock write_ptr)+ , blk_no == write_blk_no+ , Just Refl <- testEquality w (ptrWidth write_ptr)+ , Just write_off <- asBV (llvmPointerOffset write_ptr)+ , Just sz_bv <- asBV sz+ , MemCopy src_ptr mem_copy_sz <- write_source+ , Just mem_copy_sz_bv <- asBV mem_copy_sz+ , BV.ule write_off off+ , BV.ule (BV.add w off sz_bv) (BV.add w write_off mem_copy_sz_bv)+ , Just src_blk_no <- asNat (llvmPointerBlock src_ptr)+ , Just src_off <- asBV (llvmPointerOffset src_ptr) ->+ findArrayStore sym w src_blk_no (BV.add w src_off $ BV.sub w off write_off) sz memo_cont tail_mem_writes - | otherwise -> return Nothing+ | Just write_blk_no <- asNat (llvmPointerBlock write_ptr)+ , blk_no == write_blk_no+ , Just Refl <- testEquality w (ptrWidth write_ptr)+ , Just write_off <- asBV (llvmPointerOffset write_ptr)+ , Just sz_bv <- asBV sz+ , MemSet val mem_set_sz <- write_source+ , Just mem_set_sz_bv <- asBV mem_set_sz+ , BV.ule write_off off+ , BV.ule (BV.add w off sz_bv) (BV.add w write_off mem_set_sz_bv) -> do+ arr <- constantArray sym (Ctx.singleton $ BaseBVRepr w) val+ return $ Just (truePred sym, arr) - WriteMerge cond lhs_mem_writes rhs_mem_writes -> do- lhs_result <- findArrayStore blk_no sz (memWritesAtConstant blk_no lhs_mem_writes)- rhs_result <- findArrayStore blk_no sz (memWritesAtConstant blk_no rhs_mem_writes)+ | Just write_blk_no <- asNat (llvmPointerBlock write_ptr)+ , blk_no == write_blk_no+ , Just Refl <- testEquality w (ptrWidth write_ptr)+ , Just write_off <- asBV (llvmPointerOffset write_ptr) -> do+ maybe_write_sz <- runMaybeT $ writeSourceSize sym w write_source+ case maybe_write_sz of+ Just write_sz+ | Just sz_bv <- asBV sz+ , Just write_sz_bv <- asBV write_sz+ , end <- BV.add w off sz_bv+ , write_end <- BV.add w write_off write_sz_bv+ , BV.ule end write_off || BV.ule write_end off ->+ findArrayStore sym w blk_no off sz memo_cont tail_mem_writes+ _ -> return Nothing - -- Only traverse the tail if necessary, and be careful- -- only to traverse it once- case (lhs_result, rhs_result) of- (Just _, Just _) -> combineResults cond lhs_result rhs_result+ | Just write_blk_no <- asNat (llvmPointerBlock write_ptr)+ , blk_no /= write_blk_no ->+ findArrayStore sym w blk_no off sz memo_cont tail_mem_writes - (Just _, Nothing) ->- do rhs' <- findArrayStore blk_no sz tail_mem_writes- combineResults cond lhs_result rhs'+ | otherwise -> return Nothing - (Nothing, Just _) ->- do lhs' <- findArrayStore blk_no sz tail_mem_writes- combineResults cond lhs' rhs_result+ WriteMerge cond lhs_mem_writes rhs_mem_writes -> do+ -- Only traverse the tail if necessary, and be careful+ -- only to traverse it once+ memo_tail <- putMemoIO $ findArrayStore sym w blk_no off sz memo_cont tail_mem_writes - (Nothing, Nothing) -> findArrayStore blk_no sz tail_mem_writes+ lhs_result <- findArrayStore sym w blk_no off sz memo_tail (memWritesAtConstant blk_no lhs_mem_writes)+ rhs_result <- findArrayStore sym w blk_no off sz memo_tail (memWritesAtConstant blk_no rhs_mem_writes) - combineResults cond (Just (lhs_ok, lhs_arr)) (Just (rhs_ok, rhs_arr)) =- do ok <- itePred sym cond lhs_ok rhs_ok- arr <- arrayIte sym cond lhs_arr rhs_arr- pure (Just (ok,arr))+ case (lhs_result, rhs_result) of+ (Just (lhs_ok, lhs_arr), Just (rhs_ok, rhs_arr)) ->+ do ok <- itePred sym cond lhs_ok rhs_ok+ arr <- arrayIte sym cond lhs_arr rhs_arr+ pure (Just (ok,arr)) - combineResults cond (Just (lhs_ok, lhs_arr)) Nothing =- do ok <- andPred sym cond lhs_ok- pure (Just (ok, lhs_arr))+ (Just (lhs_ok, lhs_arr), Nothing) ->+ do ok <- andPred sym cond lhs_ok+ pure (Just (ok, lhs_arr)) - combineResults cond Nothing (Just (rhs_ok, rhs_arr)) =- do cond' <- notPred sym cond- ok <- andPred sym cond' rhs_ok- pure (Just (ok, rhs_arr))+ (Nothing, Just (rhs_ok, rhs_arr)) ->+ do cond' <- notPred sym cond+ ok <- andPred sym cond' rhs_ok+ pure (Just (ok, rhs_arr)) - combineResults _cond Nothing Nothing = pure Nothing+ (Nothing, Nothing) -> pure Nothing+ {- Note [Memory Model Design]
src/Lang/Crucible/LLVM/MemModel/MemLog.hs view
@@ -56,6 +56,8 @@ , emptyChanges , emptyMem , memEndian+ , memInsertArrayBlock+ , memMemberArrayBlock -- * Pretty printing , ppType@@ -68,6 +70,7 @@ -- * Write ranges , writeRangesMem+ , writeSourceSize -- * Concretization , concPtr@@ -86,6 +89,8 @@ import Data.Map (Map) import qualified Data.Map as Map import Data.Maybe (mapMaybe)+import Data.Set (Set)+import qualified Data.Set as Set import Data.Text (Text) import Numeric.Natural import Prettyprinter@@ -247,12 +252,7 @@ Just True -> -- This is where where this block was allocated, and it -- couldn't have been freed before it was allocated.- --- -- NOTE(lb): It's not clear to me that this branch is- -- reachable: If the equality test can succeed- -- concretely, wouldn't asNat have returned a Just- -- above? In either case, this answer should be sound.- return (truePred sym, truePred sym)+ (, truePred sym) <$> inAlloc ba Just False -> k Nothing -> do (fallback', fallbackFreed') <- k@@ -325,7 +325,7 @@ -- implementation is able to efficiently merge memories, but requires -- that one only merge memories that were identical prior to the last -- branch.-data Mem sym = Mem { memEndianForm :: EndianForm, _memState :: MemState sym }+data Mem sym = Mem { memEndianForm :: EndianForm, _memState :: MemState sym, memArrayBlocks :: Set Natural } memState :: Lens' (Mem sym) (MemState sym) memState = lens _memState (\s v -> s { _memState = v })@@ -416,12 +416,22 @@ emptyChanges = (mempty, mempty) emptyMem :: EndianForm -> Mem sym-emptyMem e = Mem { memEndianForm = e, _memState = EmptyMem 0 0 emptyChanges }+emptyMem e = Mem { memEndianForm = e, _memState = EmptyMem 0 0 emptyChanges, memArrayBlocks = Set.empty } memEndian :: Mem sym -> EndianForm memEndian = memEndianForm +memInsertArrayBlock :: IsExprBuilder sym => SymNat sym -> Mem sym -> Mem sym+memInsertArrayBlock blk mem = case asNat blk of+ Just blk_no -> mem { memArrayBlocks = Set.insert blk_no (memArrayBlocks mem) }+ Nothing -> mem { memArrayBlocks = Set.empty } +memMemberArrayBlock :: IsExprBuilder sym => SymNat sym -> Mem sym -> Bool+memMemberArrayBlock blk mem = case asNat blk of+ Just blk_no -> Set.member blk_no (memArrayBlocks mem)+ Nothing -> False++ -------------------------------------------------------------------------------- -- Pretty printing @@ -526,16 +536,19 @@ multiUnion :: (Ord k, Semigroup a) => Map k a -> Map k a -> Map k a multiUnion = Map.unionWith (<>) +-- | This will return 'Just' if the size of the write is bounded and 'Nothing'+-- is the size of the write is unbounded. writeSourceSize ::- (IsExprBuilder sym, HasPtrWidth w) =>+ (IsExprBuilder sym, 1 <= w) => sym ->+ NatRepr w -> WriteSource sym w -> MaybeT IO (SymBV sym w)-writeSourceSize sym = \case+writeSourceSize sym w = \case MemCopy _src sz -> pure sz MemSet _val sz -> pure sz MemStore _val st _align ->- liftIO $ bvLit sym ?ptrWidth $ BV.mkBV ?ptrWidth $ toInteger $ typeEnd 0 st+ liftIO $ bvLit sym w $ BV.mkBV w $ toInteger $ typeEnd 0 st MemArrayStore _arr Nothing -> MaybeT $ pure Nothing MemArrayStore _arr (Just sz) -> pure sz MemInvalidate _nm sz -> pure sz@@ -550,7 +563,7 @@ | Just Refl <- testEquality ?ptrWidth (ptrWidth ptr) -> case asNat (llvmPointerBlock ptr) of Just blk -> do- sz <- writeSourceSize sym wsrc+ sz <- writeSourceSize sym ?ptrWidth wsrc pure $ Map.singleton blk [(llvmPointerOffset ptr, sz)] Nothing -> MaybeT $ pure Nothing | otherwise -> fail "foo"@@ -742,5 +755,6 @@ sym -> (forall tp. SymExpr sym tp -> IO (GroundValue tp)) -> Mem sym -> IO (Mem sym)-concMem sym conc (Mem endian st) =- Mem endian <$> concMemState sym conc st+concMem sym conc mem = do+ conc_st <- concMemState sym conc $ mem ^. memState+ return $ mem & memState .~ conc_st
src/Lang/Crucible/LLVM/MemModel/Options.hs view
@@ -67,6 +67,13 @@ -- semantics. -- -- If 'laxLoadsAndStores' is disabled, this option has no effect.++ , noSatisfyingWriteFreshConstant :: !Bool+ -- ^ If 'True', for the 'NoSatisfyingWrite' annotation, make a fresh+ -- constant as a proof obligation, which ensures it always fails. But,+ -- because it's a variable, it won't be constant-folded away and it's+ -- relatively sure the annotation will survive. If 'False', annotate+ -- 'false'. } @@ -115,6 +122,7 @@ -- The choice of StableSymbolic here doesn't matter too much, since it -- won't have any effect when laxLoadsAndStores is disabled. , indeterminateLoadBehavior = StableSymbolic+ , noSatisfyingWriteFreshConstant = True }
src/Lang/Crucible/LLVM/MemModel/Partial.hs view
@@ -46,6 +46,7 @@ , BoolAnn(..) , annotateME , annotateUB+ , ptrToBv , projectLLVM_bv , floatToBV@@ -91,7 +92,7 @@ import qualified Lang.Crucible.LLVM.Bytes as Bytes import Lang.Crucible.LLVM.MemModel.MemLog (memState) import Lang.Crucible.LLVM.MemModel.CallStack (CallStack, getCallStack)-import Lang.Crucible.LLVM.MemModel.Pointer ( pattern LLVMPointer, LLVMPtr )+import Lang.Crucible.LLVM.MemModel.Pointer ( pattern LLVMPointer, LLVMPtr, ptrIsBv ) import Lang.Crucible.LLVM.MemModel.Type (StorageType(..), StorageTypeF(..), Field(..)) import qualified Lang.Crucible.LLVM.MemModel.Type as Type import Lang.Crucible.LLVM.MemModel.Value (LLVMVal(..))@@ -262,15 +263,31 @@ (BBMemoryError (MemoryError mop rsn)) return p' +-- | Assert that the given LLVM pointer value is actually a raw bitvector and+-- extract its value.+ptrToBv ::+ IsSymBackend sym bak =>+ bak ->+ -- | Error to report if casting the pointer to a bitvector fails+ SimErrorReason ->+ LLVMPtr sym w ->+ IO (SymBV sym w)+ptrToBv bak err p@(LLVMPointer _blk bv) =+ do let sym = backendGetSym bak+ isBv <- ptrIsBv sym p+ assert bak isBv err+ return bv+ -- | Assert that the given LLVM pointer value is actually a raw bitvector and extract its value.+--+-- Note that this assertion has a very generic message, which can be unhelpful+-- to users when it fails. Consider using 'ptrToBv' instead. projectLLVM_bv :: IsSymBackend sym bak => bak -> LLVMPtr sym w -> IO (SymBV sym w)-projectLLVM_bv bak (LLVMPointer blk bv) =- do let sym = backendGetSym bak- p <- natEq sym blk =<< natLit sym 0- assert bak p $ AssertFailureSimError "Pointer value coerced to bitvector" ""- return bv+projectLLVM_bv bak ptr =+ let err = AssertFailureSimError "Pointer value coerced to bitvector" "" in+ ptrToBv bak err ptr ------------------------------------------------------------------------ -- ** PartLLVMVal@@ -366,7 +383,7 @@ floatToBV sym _ (NoErr p (LLVMValZero (StorageType Float _))) = do nz <- W4I.natLit sym 0- iz <- W4I.bvLit sym (knownNat @32) (BV.zero knownNat)+ iz <- W4I.bvZero sym (knownNat @32) return (NoErr p (LLVMValInt nz iz)) floatToBV sym _ (NoErr p (LLVMValFloat Value.SingleSize v)) =@@ -392,7 +409,7 @@ doubleToBV sym _ (NoErr p (LLVMValZero (StorageType Double _))) = do nz <- W4I.natLit sym 0- iz <- W4I.bvLit sym (knownNat @64) (BV.zero knownNat)+ iz <- W4I.bvZero sym (knownNat @64) return (NoErr p (LLVMValInt nz iz)) doubleToBV sym _ (NoErr p (LLVMValFloat Value.DoubleSize v)) =@@ -924,7 +941,7 @@ LLVMValInt base off -> do zbase <- W4I.natLit sym 0- zoff <- W4I.bvLit sym (W4I.bvWidth off) (BV.zero (W4I.bvWidth off))+ zoff <- W4I.bvZero sym (W4I.bvWidth off) base' <- W4I.natIte sym cond zbase base off' <- W4I.bvIte sym cond zoff off return $ LLVMValInt base' off'
src/Lang/Crucible/LLVM/MemModel/Pointer.hs view
@@ -20,6 +20,7 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-}@@ -51,17 +52,26 @@ , mkNullPointer -- * Concretization+ , ConcLLVMPtr(..)+ , concLLVMPtr+ , concLLVMPtrToSymbolic , concBV , concPtr , concPtr'+ , concPtrFn+ , concPtrFnMap+ , concToSymPtrFn+ , concToSymPtrFnMap -- * Operations on valid pointers , constOffset+ , ptrSameAlloc , ptrEq , ptrLe , ptrAdd , ptrDiff , ptrSub+ , ptrIsBv , ptrIsNull , isGlobalPointer , isGlobalPointer'@@ -74,7 +84,7 @@ , annotatePointerOffset ) where -import Control.Monad (guard)+import Control.Monad ((<=<), guard) import Data.Map (Map) import qualified Data.Map as Map (lookup) import Numeric.Natural@@ -86,14 +96,18 @@ import qualified Data.BitVector.Sized as BV import Data.Parameterized.Classes import qualified Data.Parameterized.Context as Ctx+import qualified Data.Parameterized.Map as MapF import Data.Parameterized.NatRepr import qualified Text.LLVM.AST as L +import qualified What4.Expr.GroundEval as W4GE import What4.Interface import What4.InterpretedFloatingPoint import What4.Expr (GroundValue) import Lang.Crucible.Backend+import qualified Lang.Crucible.Concretize as Conc+import Lang.Crucible.Panic (panic) import Lang.Crucible.Simulator.RegMap import Lang.Crucible.Simulator.Intrinsics import Lang.Crucible.Types@@ -109,9 +123,15 @@ deriving instance (Show (SymNat sym), Show (SymBV sym w)) => Show (LLVMPointer sym w) +-- | Retrieve this pointer\'s block number.+--+-- Use of this function is discouraged, as it is abstraction-breaking. llvmPointerBlock :: LLVMPtr sym w -> SymNat sym llvmPointerBlock (LLVMPointer blk _) = blk +-- | Retrieve this pointer\'s offset.+--+-- Use of this function is discouraged, as it is abstraction-breaking. llvmPointerOffset :: LLVMPtr sym w -> SymBV sym w llvmPointerOffset (LLVMPointer _ off) = off @@ -152,9 +172,42 @@ -- | Produce the distinguished null pointer value. mkNullPointer :: (1 <= w, IsSymInterface sym) => sym -> NatRepr w -> IO (LLVMPtr sym w)-mkNullPointer sym w = llvmPointer_bv sym =<< bvLit sym w (BV.zero w)+mkNullPointer sym w = llvmPointer_bv sym =<< bvZero sym w +-- | A concrete LLVM pointer+data ConcLLVMPtr w+ = ConcLLVMPtr+ { -- | Concrete block number+ concBlock :: Integer+ -- | Concrete offset+ , concOffset :: BV.BV w+ , concWidth :: NatRepr w+ } +-- | Concretize a symbolic pointer to a particular 'ConcLLVMPtr' that is+-- feasible in a model.+concLLVMPtr ::+ IsExprBuilder sym =>+ -- | Model from SMT solver+ (forall tp. SymExpr sym tp -> IO (GroundValue tp)) ->+ RegValue sym (LLVMPointerType w) ->+ IO (ConcLLVMPtr w)+concLLVMPtr conc (LLVMPointer blk off) =+ do concBlk <- conc (natToIntegerPure blk)+ concOff <- conc off+ pure (ConcLLVMPtr concBlk concOff (bvWidth off))++-- | Create a symbolic pointer from a concrete one+concLLVMPtrToSymbolic ::+ (IsExprBuilder sym, 1 <= w) =>+ sym ->+ ConcLLVMPtr w ->+ IO (RegValue sym (LLVMPointerType w))+concLLVMPtrToSymbolic sym (ConcLLVMPtr concBlk concOff w) = do+ symBlk <- integerToNat sym =<< intLit sym concBlk+ symOff <- bvLit sym w concOff+ pure (LLVMPointer symBlk symOff)+ concBV :: (IsExprBuilder sym, 1 <= w) => sym ->@@ -170,10 +223,7 @@ (forall tp. SymExpr sym tp -> IO (GroundValue tp)) -> RegValue sym (LLVMPointerType w) -> IO (RegValue sym (LLVMPointerType w))-concPtr sym conc (LLVMPointer blk off) =- do blk' <- integerToNat sym =<< intLit sym =<< conc =<< natToInteger sym blk- off' <- concBV sym conc off- pure (LLVMPointer blk' off')+concPtr sym conc = concLLVMPtrToSymbolic sym <=< concLLVMPtr conc concPtr' :: (IsExprBuilder sym, 1 <= w) =>@@ -183,7 +233,47 @@ IO (RegValue' sym (LLVMPointerType w)) concPtr' sym conc (RV ptr) = RV <$> concPtr sym conc ptr +type instance Conc.ConcIntrinsic "LLVM_pointer" (EmptyCtx ::> BVType w) = ConcLLVMPtr w +-- | An 'Conc.IntrinsicConcFn' for LLVM pointers+concPtrFn :: Conc.IntrinsicConcFn t "LLVM_pointer"+concPtrFn = Conc.IntrinsicConcFn $ \ctx tyCtx ptr ->+ case Ctx.viewAssign tyCtx of+ Ctx.AssignExtend (Ctx.viewAssign -> Ctx.AssignEmpty) (BVRepr _) ->+ let W4GE.GroundEvalFn ge = Conc.model ctx+ in concLLVMPtr ge ptr+ -- These are impossible by the definition of LLVMPointerImpl+ Ctx.AssignEmpty ->+ panic "LLVM.MemModel.Pointer.concPtrFn"+ [ "Impossible: LLVMPointerType empty context" ]+ Ctx.AssignExtend _ _ ->+ panic "LLVM.MemModel.Pointer.concPtrFn"+ [ "Impossible: LLVMPointerType ill-formed context" ]++-- | A singleton map suitable for use in a 'Conc.ConcCtx' if LLVM pointers are+-- the only intrinsic type in use+concPtrFnMap :: MapF.MapF SymbolRepr (Conc.IntrinsicConcFn t)+concPtrFnMap = MapF.singleton (knownSymbol @"LLVM_pointer") concPtrFn++-- | A 'Conc.IntrinsicConcToSymFn' for LLVM pointers+concToSymPtrFn :: Conc.IntrinsicConcToSymFn "LLVM_pointer"+concToSymPtrFn = Conc.IntrinsicConcToSymFn $ \sym tyCtx ptr ->+ case Ctx.viewAssign tyCtx of+ Ctx.AssignExtend (Ctx.viewAssign -> Ctx.AssignEmpty) (BVRepr _) ->+ concLLVMPtrToSymbolic sym ptr+ -- These are impossible by the definition of LLVMPointerImpl+ Ctx.AssignEmpty ->+ panic "LLVM.MemModel.Pointer.concToSymPtrFn"+ [ "Impossible: LLVMPointerType empty context" ]+ Ctx.AssignExtend _ _ ->+ panic "LLVM.MemModel.Pointer.concToSymPtrFn"+ [ "Impossible: LLVMPointerType ill-formed context" ]++-- | A singleton map suitable for use in 'Crucible.Concretize.concToSym' if LLVM+-- pointers are the only intrinsic type in use+concToSymPtrFnMap :: MapF.MapF SymbolRepr Conc.IntrinsicConcToSymFn+concToSymPtrFnMap = MapF.singleton (knownSymbol @"LLVM_pointer") concToSymPtrFn+ -- | Mux function specialized to LLVM pointer values. muxLLVMPtr :: (1 <= w) =>@@ -217,6 +307,22 @@ constOffset :: (1 <= w, IsExprBuilder sym) => sym -> NatRepr w -> G.Addr -> IO (SymBV sym w) constOffset sym w x = bvLit sym w (G.bytesToBV w x) +-- | Test whether two pointers point to the same allocation (i.e., have the same+-- block number).+--+-- Using this function is preferred to pattern matching on 'LLVMPointer' or+-- 'llvmPointerBlock', because it operates at a higher level of abstraction+-- (i.e., if the representation of pointers were changed, it could continue to+-- work as intended).+ptrSameAlloc ::+ (1 <= w, IsSymInterface sym) =>+ sym ->+ LLVMPtr sym w ->+ LLVMPtr sym w ->+ IO (Pred sym)+ptrSameAlloc sym (LLVMPointer base1 _off1) (LLVMPointer base2 _off2) =+ natEq sym base1 base2+ -- | Test whether two pointers are equal. ptrEq :: (1 <= w, IsSymInterface sym) => sym@@ -285,6 +391,20 @@ ptrSub sym _w (LLVMPointer base off1) off2 = do diff <- bvSub sym off1 off2 return (LLVMPointer base diff)++-- | Test if a pointer value is a bitvector (i.e., has a block number of 0)+--+-- Using this function is preferred to pattern matching on 'LLVMPointer' or+-- 'llvmPointerBlock', because it operates at a higher level of abstraction+-- (i.e., if the representation of pointers were changed, it could continue to+-- work as intended).+ptrIsBv ::+ IsSymInterface sym =>+ sym ->+ LLVMPtr sym w ->+ IO (Pred sym)+ptrIsBv sym (LLVMPointer blk _off) =+ natEq sym blk =<< natLit sym 0 -- | Test if a pointer value is the null pointer. ptrIsNull :: (1 <= w, IsSymInterface sym)
src/Lang/Crucible/LLVM/MemModel/Value.hs view
@@ -170,7 +170,7 @@ | Some w <- mkNatRepr (bytesToBits bytes) , Just LeqProof <- isPosNat w = do blk <- natLit sym 0- bv <- bvLit sym w (BV.zero w)+ bv <- bvZero sym w k (Just (blk, bv)) zeroInt _ _ k = k @1 Nothing @@ -313,7 +313,7 @@ Some (repr :: NatRepr w) -> case testNatCases (knownNat @0) repr of NatCaseLT (LeqProof :: LeqProof 1 w) ->- LLVMValInt <$> natLit sym 0 <*> bvLit sym repr (BV.zero repr)+ LLVMValInt <$> natLit sym 0 <*> bvZero sym repr NatCaseEQ -> panic "zeroExpandLLVMVal" ["Zero value inside Bytes"] NatCaseGT (LeqProof :: LeqProof (w + 1) 0) -> panic "zeroExpandLLVMVal" ["Impossible: (w + 1) </= 0"]
src/Lang/Crucible/LLVM/Printf.hs view
@@ -47,6 +47,8 @@ import Data.Word import qualified GHC.Stack as GHC +import Lang.Crucible.Panic (panic)+ data PrintfFlag = PrintfAlternateForm -- # | PrintfZeroPadding -- 0@@ -234,7 +236,13 @@ formatOctal i minwidth prec flags = do let digits = N.showOct (abs i) [] let precdigits = addLeadingZeros prec digits- let altdigits = if Set.member PrintfAlternateForm flags && head precdigits /= '0' then+ let leadingPrecDigit =+ case precdigits of+ d:_ -> d+ [] -> panic+ "formatOctal"+ ["Octal-formatted number with no digits"]+ let altdigits = if Set.member PrintfAlternateForm flags && leadingPrecDigit /= '0' then '0':precdigits else precdigits
src/Lang/Crucible/LLVM/QQ.hs view
@@ -42,6 +42,7 @@ data QQType = QQVar String -- ^ This constructor represents a type metavariable, e.g. @$var@ | QQIntVar String -- ^ This constructor represents a integer type metavariable, e.g. @#var@+ | QQVectorVar String QQType -- ^ This constructor represents a vector type with a metavariable for its size, e.g. @<#var x ty>@ | QQSizeT -- ^ This constructor represents an integer type that is the same width as a pointer | QQSSizeT -- ^ This constructor represents a signed integer type that is the same width as a pointer | QQPrim L.PrimType@@ -104,12 +105,13 @@ parseSeqType :: Char -> Char ->- (Int32 -> QQType -> QQType) ->+ AT.Parser seqSz ->+ (seqSz -> QQType -> QQType) -> AT.Parser QQType-parseSeqType start end cnstr =+parseSeqType start end parseSz cnstr = do void $ AT.char start AT.skipSpace- n <- AT.decimal+ n <- parseSz AT.skipSpace void $ AT.char 'x' AT.skipSpace@@ -118,6 +120,15 @@ void $ AT.char end return $! cnstr n tp +parseVectorType :: AT.Parser QQType+parseVectorType = parseSeqType '<' '>' AT.decimal QQVector++parseVectorVar :: AT.Parser QQType+parseVectorVar = parseSeqType '<' '>' parseIntVar QQVectorVar++parseArrayType :: AT.Parser QQType+parseArrayType = parseSeqType '[' ']' AT.decimal QQArray+ parseCommaSeparatedTypes :: AT.Parser [QQType] parseCommaSeparatedTypes = AT.choice [ do AT.skipSpace@@ -173,8 +184,9 @@ parseType :: AT.Parser QQType parseType = do base <- AT.choice- [ parseSeqType '<' '>' QQVector- , parseSeqType '[' ']' QQArray+ [ parseVectorType+ , parseVectorVar+ , parseArrayType , parseStructType , parsePackedStructType , QQVar <$> parseVar@@ -226,6 +238,7 @@ case tp of QQVar nm -> varE (mkName nm) QQIntVar nm -> [| L.PrimType (L.Integer (fromInteger (intValue $(varE (mkName nm)) ))) |]+ QQVectorVar nm t -> [| L.Vector (fromInteger (intValue $(varE (mkName nm)))) $(liftQQType t) |] QQSizeT -> varE 'IC.llvmSizeT QQSSizeT -> varE 'IC.llvmSSizeT QQAlias nm -> [| L.Alias nm |]@@ -263,6 +276,7 @@ liftTypeRepr t = case t of QQVar nm -> varE (mkName (nm++"_repr")) QQIntVar nm -> [| BVRepr $(varE (mkName nm)) |]+ QQVectorVar _ t' -> [| VectorRepr $(liftTypeRepr t') |] QQSizeT -> [| SizeT |] QQSSizeT -> [| SSizeT |] QQPrim pt -> liftPrim pt
+ src/Lang/Crucible/LLVM/SimpleLoopFixpointCHC.hs view
@@ -0,0 +1,1421 @@+------------------------------------------------------------------------+-- |+-- Module : Lang.Crucible.LLVM.SimpleLoopFixpointCHC+-- Description : Execution feature to compute loop fixpoint in+-- conjunction with CHC+-- Copyright : (c) Galois, Inc 2021+-- License : BSD3+-- Stability : provisional+--+-- This offers a similar API to what is offered in+-- "Lang.Crucible.LLVM.SimpleLoopFixpoint", but this generates proof obligations+-- involving a predicate function (named @inv@). The intent is that a user will+-- leverage Z3's constrained horn-clause (CHC) functionality to synthesize an+-- implementation of @inv@ and then substitute it back into the proof+-- obligations.+------------------------------------------------------------------------++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ImplicitParams #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE TupleSections #-}+++module Lang.Crucible.LLVM.SimpleLoopFixpointCHC+ ( FixpointEntry(..)+ , FixpointState(..)+ , CallFrameContext(..)+ , SomeCallFrameContext(..)+ , ExecutionFeatureContext(..)+ , simpleLoopFixpoint+ ) where++import Control.Lens+import Control.Monad+import Control.Monad.IO.Class+import Control.Monad.Reader+import Control.Monad.State+import Control.Monad.Trans.Maybe+import Data.Foldable+import qualified Data.IntMap as IntMap+import Data.IORef+import Data.Kind+import qualified Data.List as List+import Data.Maybe+import qualified Data.Map as Map+import Data.Map (Map)+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import Data.Set (Set)+import GHC.TypeLits (KnownNat)+import Numeric.Natural (Natural)+import qualified System.IO++import qualified Data.BitVector.Sized as BV+import Data.Parameterized.Classes+import qualified Data.Parameterized.Context as Ctx+import qualified Data.Parameterized.Map as MapF+import Data.Parameterized.Map (MapF)+import Data.Parameterized.NatRepr+import Data.Parameterized.Some+import Data.Parameterized.TraversableF+import Data.Parameterized.TraversableFC++import qualified What4.Config as W4+import qualified What4.Expr.Builder as W4+import qualified What4.Interface as W4+import qualified What4.Solver as W4++import qualified Lang.Crucible.Analysis.Fixpoint.Components as C+import qualified Lang.Crucible.Backend as C+import qualified Lang.Crucible.CFG.Core as C+import qualified Lang.Crucible.FunctionHandle as C+import qualified Lang.Crucible.Panic as C+import qualified Lang.Crucible.Simulator.CallFrame as C+import qualified Lang.Crucible.Simulator.EvalStmt as C+import qualified Lang.Crucible.Simulator.ExecutionTree as C+import qualified Lang.Crucible.Simulator.GlobalState as C+import qualified Lang.Crucible.Simulator.Operations as C+import qualified Lang.Crucible.Simulator.RegMap as C+import qualified Lang.Crucible.Simulator as C++import qualified Lang.Crucible.LLVM.Bytes as C+import qualified Lang.Crucible.LLVM.DataLayout as C+import qualified Lang.Crucible.LLVM.MemModel as C+import qualified Lang.Crucible.LLVM.MemModel.MemLog as C hiding (Mem)+import qualified Lang.Crucible.LLVM.MemModel.Pointer as C+import qualified Lang.Crucible.LLVM.MemModel.Type as C+-- import qualified Lang.Crucible.LLVM.MemModel.Generic as C (writeArrayMem)+++-- | When live loop-carried dependencies are discovered as we traverse+-- a loop body, new "widening" variables are introduced to stand in+-- for those locations. When we introduce such a variable, we+-- capture what value the variable had when we entered the loop (the+-- \"header\" value); this is essentially the initial value of the+-- variable. We also compute what value the variable should take on+-- its next iteration assuming the loop doesn't exit and executes+-- along its backedge. This \"body\" value will be computed in+-- terms of the the set of all discovered live variables so far.+-- We know we have reached fixpoint when we don't need to introduce+-- and more fresh widening variables, and the body values for each+-- variable are stable across iterations.+data FixpointEntry sym tp = FixpointEntry+ { headerValue :: W4.SymExpr sym tp+ , bodyValue :: W4.SymExpr sym tp+ }++instance OrdF (W4.SymExpr sym) => OrdF (FixpointEntry sym) where+ compareF x y = joinOrderingF+ (compareF (headerValue x) (headerValue y))+ (compareF (bodyValue x) (bodyValue y))+instance OrdF (FixpointEntry sym) => W4.TestEquality (FixpointEntry sym) where+ testEquality x y = orderingF_refl $ compareF x y++data MemLocation sym w = MemLocation+ { memLocationBlock :: Natural+ , memLocationOffset :: W4.SymBV sym w+ , memLocationSize :: W4.SymBV sym w+ }++instance OrdF (W4.SymExpr sym) => Ord (MemLocation sym w) where+ compare x y =+ compare (memLocationBlock x) (memLocationBlock y)+ <> toOrdering (compareF (memLocationOffset x) (memLocationOffset y))+ <> toOrdering (compareF (memLocationSize x) (memLocationSize y))+instance OrdF (W4.SymExpr sym) => Eq (MemLocation sym w) where+ x == y = EQ == compare x y++data MemFixpointEntry sym wptr where+ MemStoreFixpointEntry ::+ (1 <= w) =>+ W4.SymBV sym w {- ^ bitvector join variable -} ->+ C.StorageType ->+ MemFixpointEntry sym wptr+ MemArrayFixpointEntry ::+ W4.SymArray sym (C.SingleCtx (W4.BaseBVType wptr)) (W4.BaseBVType 8) {- ^ array join variable -} ->+ W4.SymBV sym wptr {- ^ length of the allocation -} ->+ MemFixpointEntry sym wptr+++-- | This datatype captures the state machine that progresses as we+-- attempt to compute a loop invariant for a simple structured loop.+data FixpointState sym wptr blocks args+ -- | We have not yet encoundered the loop head+ = BeforeFixpoint++ -- | We have encountered the loop head at least once, and are in the process+ -- of converging to an inductive representation of the live variables+ -- in the loop.+ | ComputeFixpoint (FixpointRecord sym wptr blocks args)++ -- | We have found an inductively-strong representation of the live variables+ -- of the loop, and have discovered the loop index structure controling the+ -- execution of the loop. We are now executing the loop once more to compute+ -- verification conditions for executions that reamain in the loop.+ | CheckFixpoint+ (FixpointRecord sym wptr blocks args)+ (W4.SomeSymFn sym) -- ^ function that represents the loop invariant+ (Some (Ctx.Assignment (W4.SymExpr sym))) -- ^ arguments to the loop invariant+ (W4.Pred sym) -- ^ predicate that represents the loop condition++ -- | Finally, we stitch everything we have found together into the rest of the program.+ -- Starting from the loop header one final time, we now force execution to exit the loop+ -- and continue into the rest of the program.+ | AfterFixpoint+ (FixpointRecord sym wptr blocks args)++-- | Data about the loop that we incrementally compute as we approach fixpoint.+data FixpointRecord sym wptr blocks args = FixpointRecord+ {+ -- | Block identifier of the head of the loop+ fixpointBlockId :: C.BlockID blocks args++ -- | identifier for the currently-active assumption frame related to this fixpoint computation+ , fixpointAssumptionFrameIdentifier :: C.FrameIdentifier++ -- | Map from introduced widening variables to prestate value before the loop starts,+ -- and to the value computed in a single loop iteration, assuming we return to the+ -- loop header. These variables may appear only in either registers or memory.+ , fixpointSubstitution :: MapF (W4.SymExpr sym) (FixpointEntry sym)++ -- | Prestate values of the Crucible registers when the loop header is first encountered.+ , fixpointRegMap :: C.RegMap sym args++ -- | Triples are (blockId, offset, size) to bitvector-typed entries ( bitvector only/not pointers )+ , fixpointMemSubstitution :: Map (MemLocation sym wptr) (MemFixpointEntry sym wptr)++ , fixpointEqualitySubstitution :: MapF (W4.SymExpr sym) (W4.SymExpr sym)++ -- | The loop index variable+ , fixpointIndex :: W4.SymBV sym wptr+ }+++data CallFrameContext sym wptr ext init ret blocks = CallFrameContext+ { callFrameContextFixpointStates :: MapF (C.BlockID blocks) (FixpointState sym wptr blocks)+ , callFrameContextLoopHeaders :: [C.Some (C.BlockID blocks)]+ , callFrameContextCFG :: C.CFG ext blocks init ret+ , callFrameContextParentLoop :: Map (C.Some (C.BlockID blocks)) (C.Some (C.BlockID blocks))+ , callFrameContextLoopHeaderBlockIds :: Set (C.Some (C.BlockID blocks))+ }++data CallFrameHandle init ret blocks = CallFrameHandle (C.FnHandle init ret) (Ctx.Assignment (Ctx.Assignment C.TypeRepr) blocks)+ deriving (Eq, Ord, Show)++data SomeCallFrameContext sym wptr ext init ret =+ forall blocks . SomeCallFrameContext (CallFrameContext sym wptr ext init ret blocks)++unwrapSomeCallFrameContext ::+ Ctx.Assignment (Ctx.Assignment C.TypeRepr) blocks ->+ SomeCallFrameContext sym wptr ext init ret ->+ CallFrameContext sym wptr ext init ret blocks+unwrapSomeCallFrameContext blocks_repr (SomeCallFrameContext ctx) =+ case W4.testEquality blocks_repr (fmapFC C.blockInputs $ C.cfgBlockMap $ callFrameContextCFG ctx) of+ Just Refl -> ctx+ Nothing -> C.panic "SimpleLoopFixpoint.unwrapSomeCallFrameContext" ["type mismatch"]++data ExecutionFeatureContext sym wptr ext = ExecutionFeatureContext+ { executionFeatureContextFixpointStates :: C.FnHandleMap (SomeCallFrameContext sym wptr ext)+ , executionFeatureContextInvPreds :: [W4.SomeSymFn sym]+ , executionFeatureContextLoopFunEquivConds :: [W4.Pred sym]+ }++callFrameContextLookup ::+ CallFrameHandle init ret blocks ->+ ExecutionFeatureContext sym wptr ext ->+ CallFrameContext sym wptr ext init ret blocks+callFrameContextLookup (CallFrameHandle hdl blocks_repr) ctx =+ unwrapSomeCallFrameContext blocks_repr $+ fromMaybe (C.panic "SimpleLoopFixpoint.callFrameContextLookup" ["missing call frame context", show hdl]) $+ C.lookupHandleMap hdl (executionFeatureContextFixpointStates ctx)++callFrameContextUpdate ::+ CallFrameHandle init ret blocks ->+ (CallFrameContext sym wptr ext init ret blocks -> CallFrameContext sym wptr ext init ret blocks) ->+ ExecutionFeatureContext sym wptr ext ->+ ExecutionFeatureContext sym wptr ext+callFrameContextUpdate (CallFrameHandle hdl blocks_repr) f ctx =+ ctx+ { executionFeatureContextFixpointStates = C.updateHandleMap+ (SomeCallFrameContext . f . unwrapSomeCallFrameContext blocks_repr)+ hdl+ (executionFeatureContextFixpointStates ctx)+ }++callFrameContextLookup' ::+ CallFrameHandle init ret blocks ->+ C.BlockID blocks args ->+ ExecutionFeatureContext sym wptr ext ->+ Maybe (FixpointState sym wptr blocks args)+callFrameContextLookup' hdl bid ctx =+ MapF.lookup bid $ callFrameContextFixpointStates $ callFrameContextLookup hdl ctx++callFrameContextInsert ::+ CallFrameHandle init ret blocks ->+ C.BlockID blocks args ->+ FixpointState sym wptr blocks args ->+ ExecutionFeatureContext sym wptr ext ->+ ExecutionFeatureContext sym wptr ext+callFrameContextInsert hdl bid fs =+ callFrameContextUpdate hdl $+ \ctx -> ctx { callFrameContextFixpointStates = MapF.insert bid fs (callFrameContextFixpointStates ctx) }++callFrameContextPush ::+ CallFrameHandle init ret blocks ->+ C.Some (C.BlockID blocks) ->+ ExecutionFeatureContext sym wptr ext ->+ ExecutionFeatureContext sym wptr ext+callFrameContextPush hdl bid =+ callFrameContextUpdate hdl $+ \ctx -> ctx { callFrameContextLoopHeaders = bid : callFrameContextLoopHeaders ctx }++-- | Precondition: the context's 'callFrameContextLoopHeaders' should be+-- non-empty.+callFrameContextPop ::+ CallFrameHandle init ret blocks ->+ ExecutionFeatureContext sym wptr ext ->+ ExecutionFeatureContext sym wptr ext+callFrameContextPop hdl =+ callFrameContextUpdate hdl $+ \ctx -> ctx { callFrameContextLoopHeaders =+ case callFrameContextLoopHeaders ctx of+ _:hdrs -> hdrs+ [] -> C.panic "callFrameContextPop"+ ["Empty callFrameContextLoopHeaders"] }++callFrameContextPeek ::+ CallFrameHandle init ret blocks ->+ ExecutionFeatureContext sym wptr ext ->+ Maybe (C.Some (C.BlockID blocks))+callFrameContextPeek hdl ctx =+ listToMaybe $ callFrameContextLoopHeaders $ callFrameContextLookup hdl ctx++callFrameContextLoopHeaderBlockIds' ::+ CallFrameHandle init ret blocks ->+ ExecutionFeatureContext sym wptr ext ->+ Set (C.Some (C.BlockID blocks))+callFrameContextLoopHeaderBlockIds' hdl =+ callFrameContextLoopHeaderBlockIds . callFrameContextLookup hdl++callFrameContextParentLoop' ::+ CallFrameHandle init ret blocks ->+ ExecutionFeatureContext sym wptr ext ->+ Map (C.Some (C.BlockID blocks)) (C.Some (C.BlockID blocks))+callFrameContextParentLoop' hdl =+ callFrameContextParentLoop . callFrameContextLookup hdl++executionFeatureContextAddCallFrameContext ::+ CallFrameHandle init ret blocks ->+ CallFrameContext sym wptr ext init ret blocks ->+ ExecutionFeatureContext sym wptr ext ->+ ExecutionFeatureContext sym wptr ext+executionFeatureContextAddCallFrameContext (CallFrameHandle hdl _blocks_repr) ctx context =+ context+ { executionFeatureContextFixpointStates =+ C.insertHandleMap hdl (SomeCallFrameContext ctx) (executionFeatureContextFixpointStates context)+ }++executionFeatureContextAddInvPred ::+ W4.SomeSymFn sym ->+ ExecutionFeatureContext sym wptr ext ->+ ExecutionFeatureContext sym wptr ext+executionFeatureContextAddInvPred inv_pred context =+ context { executionFeatureContextInvPreds = inv_pred : executionFeatureContextInvPreds context }++executionFeatureContextAddLoopFunEquivCond ::+ W4.Pred sym ->+ ExecutionFeatureContext sym wptr ext ->+ ExecutionFeatureContext sym wptr ext+executionFeatureContextAddLoopFunEquivCond cond context =+ context { executionFeatureContextLoopFunEquivConds = cond : executionFeatureContextLoopFunEquivConds context }+++newtype FixpointMonad sym a =+ FixpointMonad (StateT (MapF (W4.SymExpr sym) (FixpointEntry sym)) IO a)+ deriving (Functor, Applicative, Monad, MonadIO, MonadFail)++deriving instance s ~ MapF (W4.SymExpr sym) (FixpointEntry sym) => MonadState s (FixpointMonad sym)++runFixpointMonad ::+ FixpointMonad sym a ->+ MapF (W4.SymExpr sym) (FixpointEntry sym) ->+ IO (a, MapF (W4.SymExpr sym) (FixpointEntry sym))+runFixpointMonad (FixpointMonad m) = runStateT m+++joinRegEntries ::+ (?logMessage :: String -> IO (), C.IsSymInterface sym) =>+ sym ->+ Ctx.Assignment (C.RegEntry sym) ctx ->+ Ctx.Assignment (C.RegEntry sym) ctx ->+ FixpointMonad sym (Ctx.Assignment (C.RegEntry sym) ctx)+joinRegEntries sym = Ctx.zipWithM (joinRegEntry sym)++joinRegEntry ::+ (?logMessage :: String -> IO (), C.IsSymInterface sym) =>+ sym ->+ C.RegEntry sym tp ->+ C.RegEntry sym tp ->+ FixpointMonad sym (C.RegEntry sym tp)+joinRegEntry sym left right = case C.regType left of+ C.LLVMPointerRepr w++ -- special handling for "don't care" registers coming from Macaw+ | List.isPrefixOf "cmacaw_reg" (show $ W4.printSymNat $ C.llvmPointerBlock (C.regValue left))+ , List.isPrefixOf "cmacaw_reg" (show $ W4.printSymExpr $ C.llvmPointerOffset (C.regValue left)) -> do+ liftIO $ ?logMessage "SimpleLoopFixpoint.joinRegEntry: cmacaw_reg"+ return left++ | C.llvmPointerBlock (C.regValue left) == C.llvmPointerBlock (C.regValue right) -> do+ liftIO $ ?logMessage "SimpleLoopFixpoint.joinRegEntry: LLVMPointerRepr"+ subst <- get+ if isJust (W4.testEquality (C.llvmPointerOffset (C.regValue left)) (C.llvmPointerOffset (C.regValue right)))+ then do+ liftIO $ ?logMessage "SimpleLoopFixpoint.joinRegEntry: LLVMPointerRepr: left == right"+ return left+ else case MapF.lookup (C.llvmPointerOffset (C.regValue left)) subst of+ Just join_entry -> do+ liftIO $ ?logMessage $+ "SimpleLoopFixpoint.joinRegEntry: LLVMPointerRepr: Just: "+ ++ show (W4.printSymExpr $ bodyValue join_entry)+ ++ " -> "+ ++ show (W4.printSymExpr $ C.llvmPointerOffset (C.regValue right))+ put $ MapF.insert+ (C.llvmPointerOffset (C.regValue left))+ (join_entry { bodyValue = C.llvmPointerOffset (C.regValue right) })+ subst+ return left+ Nothing -> do+ liftIO $ ?logMessage "SimpleLoopFixpoint.joinRegEntry: LLVMPointerRepr: Nothing"+ join_variable <- liftIO $ W4.freshConstant sym (W4.safeSymbol "reg_join_var") (W4.BaseBVRepr w)+ let join_entry = FixpointEntry+ { headerValue = C.llvmPointerOffset (C.regValue left)+ , bodyValue = C.llvmPointerOffset (C.regValue right)+ }+ put $ MapF.insert join_variable join_entry subst+ return $ C.RegEntry (C.LLVMPointerRepr w) $ C.LLVMPointer (C.llvmPointerBlock (C.regValue left)) join_variable+ | Just{} <- W4.asConcrete (C.llvmPointerOffset (C.regValue left)) -> do+ return $ C.RegEntry (C.LLVMPointerRepr w) $ C.LLVMPointer (C.llvmPointerBlock (C.regValue left)) (C.llvmPointerOffset (C.regValue left))+ | otherwise ->+ fail $+ "SimpleLoopFixpoint.joinRegEntry: LLVMPointerRepr: unsupported pointer base join: "+ ++ show (C.ppPtr $ C.regValue left)+ ++ " \\/ "+ ++ show (C.ppPtr $ C.regValue right)++ C.BoolRepr+ | List.isPrefixOf "cmacaw" (show $ W4.printSymExpr $ C.regValue left) -> do+ liftIO $ ?logMessage "SimpleLoopFixpoint.joinRegEntry: cmacaw_reg"+ return left+ | otherwise -> do+ liftIO $ ?logMessage $+ "SimpleLoopFixpoint.joinRegEntry: BoolRepr:"+ ++ show (W4.printSymExpr $ C.regValue left)+ ++ " \\/ "+ ++ show (W4.printSymExpr $ C.regValue right)+ join_varaible <- liftIO $ W4.freshConstant sym (W4.safeSymbol "macaw_reg") W4.BaseBoolRepr+ return $ C.RegEntry C.BoolRepr join_varaible++ C.StructRepr field_types -> do+ liftIO $ ?logMessage "SimpleLoopFixpoint.joinRegEntry: StructRepr"+ C.RegEntry (C.regType left) <$> fmapFC (C.RV . C.regValue) <$> joinRegEntries sym+ (Ctx.generate (Ctx.size field_types) $ \i ->+ C.RegEntry (field_types Ctx.! i) $ C.unRV $ (C.regValue left) Ctx.! i)+ (Ctx.generate (Ctx.size field_types) $ \i ->+ C.RegEntry (field_types Ctx.! i) $ C.unRV $ (C.regValue right) Ctx.! i)+ _ -> fail $ "SimpleLoopFixpoint.joinRegEntry: unsupported type: " ++ show (C.regType left)+++applySubstitutionRegEntries ::+ C.IsSymInterface sym =>+ sym ->+ MapF (W4.SymExpr sym) (W4.SymExpr sym) ->+ Ctx.Assignment (C.RegEntry sym) ctx ->+ Ctx.Assignment (C.RegEntry sym) ctx+applySubstitutionRegEntries sym substitution = fmapFC (applySubstitutionRegEntry sym substitution)++applySubstitutionRegEntry ::+ C.IsSymInterface sym =>+ sym ->+ MapF (W4.SymExpr sym) (W4.SymExpr sym) ->+ C.RegEntry sym tp ->+ C.RegEntry sym tp+applySubstitutionRegEntry sym substitution entry = case C.regType entry of+ C.LLVMPointerRepr{} ->+ entry+ { C.regValue = C.LLVMPointer+ (C.llvmPointerBlock (C.regValue entry))+ (MapF.findWithDefault+ (C.llvmPointerOffset (C.regValue entry))+ (C.llvmPointerOffset (C.regValue entry))+ substitution)+ }+ C.BoolRepr ->+ entry+ C.StructRepr field_types ->+ entry+ { C.regValue = fmapFC (C.RV . C.regValue) $+ applySubstitutionRegEntries sym substitution $+ Ctx.generate (Ctx.size field_types) $+ \i -> C.RegEntry (field_types Ctx.! i) $ C.unRV $ (C.regValue entry) Ctx.! i+ }+ _ -> C.panic "SimpleLoopFixpoint.applySubstitutionRegEntry" ["unsupported type: " ++ show (C.regType entry)]+++joinMem ::+ forall sym wptr .+ (C.IsSymInterface sym, C.HasPtrWidth wptr) =>+ sym ->+ C.MemImpl sym ->+ C.MemWrites sym ->+ IO (Map (MemLocation sym wptr) (MemFixpointEntry sym wptr))+joinMem sym mem_impl mem_writes = do+ ranges <- maybe (fail "SimpleLoopFixpoint: unsupported symbolic pointers") return =<<+ runMaybeT (C.writeRangesMem @_ @wptr sym $ C.memImplHeap mem_impl)++ mem_subst <- case mem_writes of+ C.MemWrites [C.MemWritesChunkIndexed indexed_writes] -> Map.fromList . catMaybes <$> mapM+ (\case+ C.MemWrite ptr mem_source+ | Just Refl <- W4.testEquality ?ptrWidth (C.ptrWidth ptr)+ , Just blk <- W4.asNat (C.llvmPointerBlock ptr) -> do+ sz <- maybe (fail "SimpleLoopFixpoint: unsupported MemSource") return =<<+ runMaybeT (C.writeSourceSize sym (C.ptrWidth ptr) mem_source)+ let mem_loc = MemLocation+ { memLocationBlock = blk+ , memLocationOffset = C.llvmPointerOffset ptr+ , memLocationSize = sz+ }++ is_loop_local <- and <$> mapM+ (\(prev_off, prev_sz) -> do+ disjoint_pred <- C.buildDisjointRegionsAssertionWithSub+ sym+ ptr+ sz+ (C.LLVMPointer (C.llvmPointerBlock ptr) prev_off)+ prev_sz+ return $ W4.asConstantPred disjoint_pred == Just True)+ (Map.findWithDefault [] blk ranges)++ if not is_loop_local then do+ mem_entry <- case mem_source of+ C.MemStore _ storage_type _ ->+ case W4.mkNatRepr $ C.bytesToBits (C.typeEnd 0 storage_type) of+ C.Some bv_width+ | Just C.LeqProof <- W4.testLeq (W4.knownNat @1) bv_width -> do+ join_variable <- W4.freshConstant sym (W4.safeSymbol "mem_join_var") (W4.BaseBVRepr bv_width)+ return $ MemStoreFixpointEntry join_variable storage_type+ | otherwise ->+ C.panic+ "SimpleLoopFixpoint.simpleLoopFixpoint"+ ["unexpected storage type " ++ show storage_type]++ C.MemArrayStore arr _ -> do+ join_variable <- W4.freshConstant sym (W4.safeSymbol "mem_join_var") (W4.exprType arr)+ return $ MemArrayFixpointEntry join_variable sz++ _ -> fail "SimpleLoopFixpoint.joinMem: unsupported MemSource"++ return $ Just (mem_loc, mem_entry)++ else+ return Nothing++ _ -> fail $ "SimpleLoopFixpoint: not MemWrite: " ++ show (C.ppMemWrites mem_writes))+ (List.concat $ IntMap.elems indexed_writes)++ C.MemWrites [] -> return Map.empty++ _ -> fail $ "SimpleLoopFixpoint: not MemWritesChunkIndexed: " ++ show (C.ppMemWrites mem_writes)++ checkDisjointRegions sym $ Map.keys mem_subst++ return mem_subst++checkDisjointRegions ::+ (C.IsSymInterface sym, C.HasPtrWidth wptr) =>+ sym ->+ [MemLocation sym wptr] ->+ IO ()+checkDisjointRegions sym = \case+ hd_mem_loc : tail_mem_locs -> do+ mapM_ (checkDisjointRegions' sym hd_mem_loc) tail_mem_locs+ checkDisjointRegions sym tail_mem_locs+ [] -> return ()++checkDisjointRegions' ::+ (C.IsSymInterface sym, C.HasPtrWidth wptr) =>+ sym ->+ MemLocation sym wptr ->+ MemLocation sym wptr ->+ IO ()+checkDisjointRegions' sym mem_loc1 mem_loc2 = do+ ptr1 <- memLocationPtr sym mem_loc1+ ptr2 <- memLocationPtr sym mem_loc2+ disjoint_pred <- C.buildDisjointRegionsAssertionWithSub+ sym+ ptr1+ (memLocationSize mem_loc1)+ ptr2+ (memLocationSize mem_loc2)+ when (W4.asConstantPred disjoint_pred /= Just True) $+ fail $+ "SimpleLoopFixpoint: non-disjoint ranges: off1="+ ++ show (W4.printSymExpr $ C.llvmPointerOffset ptr1)+ ++ ", sz1="+ ++ show (W4.printSymExpr $ memLocationSize mem_loc1)+ ++ ", off2="+ ++ show (W4.printSymExpr $ C.llvmPointerOffset ptr2)+ ++ ", sz2="+ ++ show (W4.printSymExpr $ memLocationSize mem_loc2)+++loadMemJoinVariables ::+ (C.IsSymBackend sym bak, C.HasPtrWidth wptr, C.HasLLVMAnn sym, ?memOpts :: C.MemOptions) =>+ bak ->+ C.MemImpl sym ->+ Map (MemLocation sym wptr) (MemFixpointEntry sym wptr) ->+ IO (MapF (W4.SymExpr sym) (W4.SymExpr sym))+loadMemJoinVariables bak mem subst =+ let sym = C.backendGetSym bak in+ MapF.fromList . catMaybes <$> mapM+ (\(mem_loc, mem_entry) -> do+ ptr <- memLocationPtr sym mem_loc+ case mem_entry of+ MemStoreFixpointEntry join_variable storage_type -> do+ val <- C.doLoad bak mem ptr storage_type (C.LLVMPointerRepr $ W4.bvWidth join_variable) C.noAlignment+ case W4.asNat (C.llvmPointerBlock val) of+ Just 0 -> return $ Just $ MapF.Pair join_variable $ C.llvmPointerOffset val+ _ -> fail $ "SimpleLoopFixpoint.loadMemJoinVariables: unexpected val:" ++ show (C.ppPtr val)+ -- foo <- C.loadRaw sym mem ptr storage_type C.noAlignment+ -- case foo of+ -- C.NoErr _p val' -> do+ -- val <- C.unpackMemValue sym (C.LLVMPointerRepr $ W4.bvWidth join_variable) val'+ -- case W4.asNat (C.llvmPointerBlock val) of+ -- Just 0 -> return $ Just $ MapF.Pair join_variable $ C.llvmPointerOffset val+ -- _ -> fail $ "SimpleLoopFixpoint.loadMemJoinVariables: unexpected val:" ++ show (C.ppPtr val)+ -- C.Err{} -> -- return Nothing+ -- fail $ "SimpleLoopFixpoint.loadMemJoinVariables: loadRaw failed"+ MemArrayFixpointEntry join_variable _size -> do+ -- TODO: handle arrays+ maybe_allocation_array <- C.asMemAllocationArrayStore sym ?ptrWidth ptr (C.memImplHeap mem)+ case maybe_allocation_array of+ Just (ok, arr, _arr_sz) | Just True <- W4.asConstantPred ok -> do+ return $ Just $ MapF.Pair join_variable arr+ _ -> fail $ "SimpleLoopFixpoint.loadMemJoinVariables")+ (Map.toAscList subst)++storeMemJoinVariables ::+ (C.IsSymBackend sym bak, C.HasPtrWidth wptr, C.HasLLVMAnn sym, ?memOpts :: C.MemOptions) =>+ bak ->+ C.MemImpl sym ->+ Map (MemLocation sym wptr) (MemFixpointEntry sym wptr) ->+ MapF (W4.SymExpr sym) (W4.SymExpr sym) ->+ IO (C.MemImpl sym)+storeMemJoinVariables bak mem mem_subst eq_subst = do+ let sym = C.backendGetSym bak+ foldlM+ (\mem_acc (mem_loc, mem_entry) -> do+ ptr <- memLocationPtr sym mem_loc+ case mem_entry of+ MemStoreFixpointEntry join_variable storage_type -> do+ C.doStore bak mem_acc ptr (C.LLVMPointerRepr $ W4.bvWidth join_variable) storage_type C.noAlignment =<<+ C.llvmPointer_bv sym (findWithDefaultKey eq_subst join_variable)+ MemArrayFixpointEntry join_variable size -> do+ C.doArrayStore bak mem_acc ptr C.noAlignment (findWithDefaultKey eq_subst join_variable) size)+ -- (heap, p1, p2) <- C.writeArrayMem+ -- sym+ -- ?ptrWidth+ -- ptr+ -- C.noAlignment+ -- (findWithDefaultKey eq_subst join_variable)+ -- (Just size)+ -- (C.memImplHeap mem_acc)+ -- return $ mem_acc { C.memImplHeap = heap })+ mem+ (Map.toAscList mem_subst)++memLocationPtr ::+ C.IsSymInterface sym =>+ sym ->+ MemLocation sym wptr ->+ IO (C.LLVMPtr sym wptr)+memLocationPtr sym (MemLocation { memLocationBlock = blk, memLocationOffset = off }) =+ C.LLVMPointer <$> W4.natLit sym blk <*> return off+++dropMemStackFrame :: C.IsSymInterface sym => C.MemImpl sym -> (C.MemImpl sym, C.MemAllocs sym, C.MemWrites sym)+dropMemStackFrame mem = case (C.memImplHeap mem) ^. C.memState of+ (C.StackFrame _ _ _ (a, w) s) -> ((mem { C.memImplHeap = (C.memImplHeap mem) & C.memState .~ s }), a, w)+ _ -> C.panic "SimpleLoopFixpoint.dropMemStackFrame" ["not a stack frame:", show (C.ppMem $ C.memImplHeap mem)]+++filterSubstitution ::+ C.IsSymInterface sym =>+ sym ->+ MapF (W4.SymExpr sym) (FixpointEntry sym) ->+ MapF (W4.SymExpr sym) (FixpointEntry sym)+filterSubstitution sym substitution =+ -- TODO: fixpoint+ let uninterp_constants = foldMapF+ (Set.map (C.mapSome $ W4.varExpr sym) . W4.exprUninterpConstants sym . bodyValue)+ substitution+ in+ MapF.filterWithKey (\variable _entry -> Set.member (C.Some variable) uninterp_constants) substitution++loopIndexLinearSubstitution ::+ (C.IsSymInterface sym, C.HasPtrWidth wptr, MonadIO m) =>+ sym ->+ W4.SymBV sym wptr ->+ MapF (W4.SymExpr sym) (FixpointEntry sym) ->+ m (MapF (W4.SymExpr sym) (W4.SymExpr sym))+loopIndexLinearSubstitution sym index_variable =+ MapF.traverseMaybeWithKey+ (\variable entry -> case W4.testEquality (W4.exprType variable) (W4.exprType index_variable) of+ Just Refl -> do+ diff <- liftIO $ W4.bvSub sym (bodyValue entry) variable+ case W4.asBV diff of+ Just{} -> liftIO $ Just <$> (W4.bvAdd sym (headerValue entry) =<< W4.bvMul sym index_variable diff)+ Nothing -> return Nothing+ Nothing -> return Nothing)++-- find widening variables that are actually the same (up to syntactic equality)+-- and can be substituted for each other+uninterpretedConstantEqualitySubstitution ::+ (C.IsSymInterface sym, sym ~ W4.ExprBuilder t st fs, MonadIO m, MonadFail m, ?logMessage :: String -> IO ()) =>+ sym ->+ MapF (W4.SymExpr sym) (FixpointEntry sym) ->+ m (MapF (W4.SymExpr sym) (FixpointEntry sym), MapF (W4.SymExpr sym) (W4.SymExpr sym))+uninterpretedConstantEqualitySubstitution sym substitution = do+ let reverse_substitution = MapF.foldlWithKey'+ (\accumulator variable entry -> MapF.insert entry variable accumulator)+ MapF.empty+ substitution+ let uninterpreted_constant_substitution =+ MapF.filterWithKey (\variable entry -> isNothing $ W4.testEquality variable entry) $+ fmapF (\entry -> fromJust $ MapF.lookup entry reverse_substitution)+ substitution+ let normal_substitution = MapF.filterWithKey+ (\variable _entry -> isNothing $ MapF.lookup variable uninterpreted_constant_substitution)+ substitution++ liftIO $ ?logMessage "vars:"+ mapM_+ (\(MapF.Pair variable entry) -> do+ let body_vars = Set.map (C.mapSome $ W4.varExpr sym) $ W4.exprUninterpConstants sym $ bodyValue entry+ liftIO $ ?logMessage $ show (W4.printSymExpr variable) ++ " :: "++ show (W4.exprType variable) ++ " -> " ++ (show $ Set.map (C.viewSome $ show . W4.printSymExpr) $ body_vars))+ (MapF.toList normal_substitution)++ foo <- MapF.fromList <$> filterM+ (\(MapF.Pair variable entry) -> do+ let body_vars = Set.map (C.mapSome $ W4.varExpr sym) $ W4.exprUninterpConstants sym $ bodyValue entry+ if Set.notMember (C.Some variable) body_vars then do+ let lalala = runIdentity $ MapF.fromKeysM (return . W4.varExpr sym) $ W4.exprUninterpConstants sym $ bodyValue entry+ let foobar = fmapF headerValue $ MapF.mapMaybe (\v -> MapF.lookup v normal_substitution) lalala+ bar <- liftIO $ W4.isEq sym (headerValue entry) =<< W4.substituteBoundVars sym foobar (bodyValue entry)+ liftIO $ ?logMessage $ "la: " ++ (show $ W4.printSymExpr variable)+ liftIO $ ?logMessage $ "headerValue entry: " ++ (show $ W4.printSymExpr $ headerValue entry)+ liftIO $ ?logMessage $ "bodyValue entry:" ++ (show $ W4.printSymExpr $ bodyValue entry)+ liftIO $ ?logMessage $ "bar: " ++ (show $ W4.printSymExpr $ bar)+ if Just True == W4.asConstantPred bar then do+ liftIO $ ?logMessage "lala"+ return True+ else do+ notbar <- liftIO $ W4.notPred sym bar+ lala <- liftIO $ W4.runZ3InOverride sym (W4.defaultLogData { W4.logVerbosity = 2 }) [notbar] $ return . W4.isUnsat+ when lala $ do+ liftIO $ ?logMessage "lalala"+ return lala+ else+ return False)+ (MapF.toList normal_substitution)++ unless (Set.disjoint (Set.fromList $ MapF.keys foo) (foldMapF (Set.map (C.mapSome $ W4.varExpr sym) . W4.exprUninterpConstants sym) $ fmapF bodyValue foo)) $+ fail "SimpleLoopFixpoint: uninterpretedConstantEqualitySubstitution: not disjoint"++ return+ ( MapF.mergeWithKey (\_ _ _ -> Nothing) id (const MapF.empty) normal_substitution foo -- difference+ , MapF.mergeWithKey (\_ _ -> Just) id id uninterpreted_constant_substitution $ fmapF bodyValue foo -- union+ )+++-- -- | Given the WTO analysis results, find the nth loop.+-- -- Return the identifier of the loop header, and a list of all the blocks+-- -- that are part of the loop body. It is at this point that we check+-- -- that the loop has the necessary properties; there must be a single+-- -- entry point to the loop, and it must have a single back-edge. Otherwise,+-- -- the analysis will not work correctly.+-- computeLoopBlocks :: forall ext blocks init ret k .+-- (k ~ C.Some (C.BlockID blocks)) =>+-- C.CFG ext blocks init ret ->+-- Integer ->+-- IO (k, [k])+-- computeLoopBlocks cfg loopNum =+-- case List.genericDrop loopNum (Map.toList loop_map) of+-- [] -> fail ("Did not find " ++ show loopNum ++ " loop headers")+-- (p:_) -> do checkSingleEntry p+-- checkSingleBackedge p+-- return p++-- where+-- -- There should be exactly one block which is not part of the loop body that+-- -- can jump to @hd@.+-- checkSingleEntry :: (k,[k]) -> IO ()+-- checkSingleEntry (hd, body) =+-- case filter (\x -> not (elem x body) && elem hd (C.cfgSuccessors cfg x)) allReachable of+-- [_] -> return ()+-- _ -> fail "SimpleLoopInvariant feature requires a single-entry loop!"++-- -- There should be exactly on block in the loop body which can jump to @hd@.+-- checkSingleBackedge :: (k,[k]) -> IO ()+-- checkSingleBackedge (hd, body) =+-- case filter (\x -> elem hd (C.cfgSuccessors cfg x)) body of+-- [_] -> return ()+-- _ -> fail "SimpleLoopInvariant feature requires a loop with a single backedge!"++-- flattenWTOComponent = \case+-- C.SCC C.SCCData{..} -> wtoHead : concatMap flattenWTOComponent wtoComps+-- C.Vertex v -> [v]++-- loop_map = Map.fromList $ mapMaybe+-- (\case+-- C.SCC C.SCCData{..} -> Just (wtoHead, wtoHead : concatMap flattenWTOComponent wtoComps)+-- C.Vertex{} -> Nothing)+-- wto++-- allReachable = concatMap flattenWTOComponent wto++-- wto = C.cfgWeakTopologicalOrdering cfg+++-- | This execution feature is designed to allow a limited form of+-- verification for programs with unbounded looping structures.+--+-- It is currently highly experimental and has many limitations.+-- Most notably, it only really works properly for functions+-- consisting of a single, non-nested loop with a single exit point.+-- Moreover, the loop must have an indexing variable that counts up+-- from a starting point by a fixed stride amount.+--+-- Currently, these assumptions about the loop structure are not+-- checked.+--+-- The basic use case here is for verifying functions that loop+-- through an array of data of symbolic length. This is done by+-- providing a \""fixpoint function\" which describes how the live+-- values in the loop at an arbitrary iteration are used to compute+-- the final values of those variables before execution leaves the+-- loop. The number and order of these variables depends on+-- internal details of the representation, so is relatively fragile.+simpleLoopFixpoint ::+ (C.IsSymInterface sym, sym ~ W4.ExprBuilder t st fs, C.HasPtrWidth wptr, KnownNat wptr, C.HasLLVMAnn sym, ?memOpts :: C.MemOptions) =>+ sym ->+ C.CFG ext blocks init ret {- ^ The function we want to verify -} ->+ C.GlobalVar C.Mem {- ^ global variable representing memory -} ->+ Maybe (MapF (W4.SymExpr sym) (FixpointEntry sym) -> W4.Pred sym -> IO (MapF (W4.SymExpr sym) (W4.SymExpr sym), Maybe (W4.Pred sym))) ->+ IO (C.ExecutionFeature p sym ext rtp, IORef (ExecutionFeatureContext sym wptr ext))+simpleLoopFixpoint sym _cfg mem_var maybe_fixpoint_func = do+ verbSetting <- W4.getOptionSetting W4.verbosity $ W4.getConfiguration sym+ _verb <- fromInteger @Natural <$> W4.getOpt verbSetting++ -- let loop_map = Map.fromList $ mapMaybe+ -- (\case+ -- scc@(C.SCC _) -> Just (wtoHead, wtoHead : concatMap flattenWTOComponent wtoComps)+ -- C.Vertex{} -> Nothing)+ -- (C.cfgWeakTopologicalOrdering cfg)++ -- Doesn't really work if there are nested loops: looop datastructures will+ -- overwrite each other. Currently no error message.++ -- Really only works for single-exit loops; need a message for that too.++ -- let flattenWTOComponent = \case+ -- C.SCC C.SCCData{..} -> wtoHead : concatMap flattenWTOComponent wtoComps+ -- C.Vertex v -> [v]+ -- let loop_map = Map.fromList $ mapMaybe+ -- (\case+ -- C.SCC C.SCCData{..} -> Just (wtoHead, wtoHead : concatMap flattenWTOComponent wtoComps)+ -- C.Vertex{} -> Nothing)+ -- (C.cfgWeakTopologicalOrdering cfg)+++ -- let parent_wto_component = C.parentWTOComponent $ C.cfgWeakTopologicalOrdering cfg+ -- fixpoint_state_ref <- newIORef $+ -- FrameContext+ -- { frameContextFixpointStates = MapF.empty+ -- , frameContextLoopHeaders = []+ -- , frameContextCFG = cfg+ -- , frameContextParentLoop = parent_wto_component+ -- , frameContextLoopHeaderBlockIds = Set.fromList $ Map.elems parent_wto_component+ -- }++ fixpoint_state_ref <- newIORef $+ ExecutionFeatureContext+ { executionFeatureContextFixpointStates = C.emptyHandleMap+ , executionFeatureContextInvPreds = []+ , executionFeatureContextLoopFunEquivConds = []+ }++ -- initializeCallFrameContext cfg fixpoint_state_ref++ return $ (, fixpoint_state_ref) $ C.ExecutionFeature $ \exec_state -> do+ -- let ?logMessage = \msg -> when (_verb >= 3) $ do+ let ?logMessage = \msg -> do+ let h = C.printHandle $ C.execStateContext exec_state+ System.IO.hPutStrLn h msg+ System.IO.hFlush h++ -- cfg_handle <- C.cfgHandle . callFrameContextCFG <$> readIORef fixpoint_state_ref+ -- cfg_block_map <- C.cfgBlockMap . callFrameContextCFG <$> readIORef fixpoint_state_ref+ -- parent_loop_map <- callFrameContextParentLoop <$> readIORef fixpoint_state_ref+ -- loop_header_block_ids <- callFrameContextLoopHeaderBlockIds <$> readIORef fixpoint_state_ref+ -- maybe_some_loop_block_id <- callFrameContextPeek <$> readIORef fixpoint_state_ref+ C.withBackend (C.execStateContext exec_state) $ \bak -> case exec_state of+ C.RunningState (C.RunBlockStart block_id) sim_state+ | SomeCallFrameHandle call_frame_handle <- callFrameHandle (sim_state ^. C.stateCrucibleFrame) -> do+ loop_header_block_ids <- callFrameContextLoopHeaderBlockIds' call_frame_handle <$> readIORef fixpoint_state_ref+ if Set.member (C.Some block_id) loop_header_block_ids then do+ ?logMessage $ "!!!SimpleLoopFixpoint: RunningState: RunBlockStart: " ++ show block_id+ advanceFixpointState bak mem_var maybe_fixpoint_func call_frame_handle block_id sim_state fixpoint_state_ref+ else do+ ?logMessage $ "SimpleLoopFixpoint: RunningState: RunBlockStart: " ++ show block_id+ return C.ExecutionFeatureNoChange++ -- | C.SomeHandle cfg_handle == C.frameHandle (sim_state ^. C.stateCrucibleFrame)+ -- -- make sure the types match+ -- , Just Refl <- W4.testEquality+ -- (fmapFC C.blockInputs cfg_block_map)+ -- (fmapFC C.blockInputs $ C.frameBlockMap $ sim_state ^. C.stateCrucibleFrame)+ -- -- loop map is what we computed above, is this state at a loop header+ -- , Set.member (C.Some block_id) loop_header_block_ids ->+ -- advanceFixpointState bak mem_var maybe_fixpoint_func cfg_handle block_id sim_state fixpoint_state_ref++ -- | otherwise -> do+ -- ?logMessage $ "SimpleLoopFixpoint: RunningState: RunBlockStart: " ++ show block_id+ -- return C.ExecutionFeatureNoChange++ -- TODO: maybe need to rework this, so that we are sure to capture even concrete exits from the loop.+ C.SymbolicBranchState branch_condition true_frame false_frame _target sim_state+ | JustPausedFrameTgtId true_frame_some_block_id <- pausedFrameTgtId true_frame+ , JustPausedFrameTgtId false_frame_some_block_id <- pausedFrameTgtId false_frame+ , SomeCallFrameHandle call_frame_handle <- callFrameHandle (sim_state ^. C.stateCrucibleFrame) -> do+ maybe_some_loop_block_id <- callFrameContextPeek call_frame_handle <$> readIORef fixpoint_state_ref+ parent_loop_map <- callFrameContextParentLoop' call_frame_handle <$> readIORef fixpoint_state_ref+ -- , C.SomeHandle cfg_handle == C.frameHandle (sim_state ^. C.stateCrucibleFrame)+ -- , Just Refl <- W4.testEquality+ -- (fmapFC C.blockInputs cfg_block_map)+ -- (fmapFC C.blockInputs $ C.frameBlockMap $ sim_state ^. C.stateCrucibleFrame)+ -- , Just (Some loop_block_id) <- maybe_some_loop_block_id+ -- , true_frame_parent_loop_id <- Map.lookup true_frame_some_block_id parent_loop_map+ -- , false_frame_parent_loop_id <- Map.lookup false_frame_some_block_id parent_loop_map+ -- , true_frame_parent_loop_id /= maybe_some_loop_block_id || false_frame_parent_loop_id /= maybe_some_loop_block_id -> do+ if| Just (Some loop_block_id) <- maybe_some_loop_block_id+ , true_frame_parent_loop_id <- if true_frame_some_block_id /= C.Some loop_block_id then Map.lookup true_frame_some_block_id parent_loop_map else maybe_some_loop_block_id+ , false_frame_parent_loop_id <- if false_frame_some_block_id /= C.Some loop_block_id then Map.lookup false_frame_some_block_id parent_loop_map else maybe_some_loop_block_id+ , true_frame_parent_loop_id /= maybe_some_loop_block_id || false_frame_parent_loop_id /= maybe_some_loop_block_id -> do+ ?logMessage $ "!!!SimpleLoopFixpoint: SymbolicBranchState: " ++ show (true_frame_some_block_id, false_frame_some_block_id)+ handleSymbolicBranch+ bak+ call_frame_handle+ loop_block_id+ branch_condition+ true_frame+ false_frame+ true_frame_parent_loop_id+ false_frame_parent_loop_id+ sim_state+ fixpoint_state_ref+ | otherwise -> do+ ?logMessage $ "SimpleLoopFixpoint: SymbolicBranchState: " ++ show (W4.printSymExpr branch_condition, true_frame_some_block_id, false_frame_some_block_id)+ return C.ExecutionFeatureNoChange++ C.CallState _return_handler (C.CrucibleCall _block_id call_frame) _sim_state+ | C.CallFrame { C._frameCFG = callee_cfg } <- call_frame -> do+ initializeCallFrameContext callee_cfg fixpoint_state_ref+ return C.ExecutionFeatureNoChange+ C.TailCallState _value_from_value (C.CrucibleCall _block_id call_frame) _sim_state+ | C.CallFrame { C._frameCFG = callee_cfg } <- call_frame -> do+ initializeCallFrameContext callee_cfg fixpoint_state_ref+ return C.ExecutionFeatureNoChange++ _ -> return C.ExecutionFeatureNoChange+++initializeCallFrameContext ::+ (?logMessage :: String -> IO ()) =>+ C.CFG ext blocks init ret ->+ IORef (ExecutionFeatureContext sym wptr ext) ->+ IO ()+initializeCallFrameContext cfg context_ref = do+ ?logMessage $ "SimpleLoopFixpoint: cfgHandle: " ++ show (C.cfgHandle cfg)+ ?logMessage $ "SimpleLoopFixpoint: cfg: " ++ show (toListFC (\b -> (C.Some (C.blockID b), C.nextBlocks b)) $ C.cfgBlockMap cfg)+ ?logMessage $ "SimpleLoopFixpoint: cfgWeakTopologicalOrdering: " ++ show (C.cfgWeakTopologicalOrdering cfg)+ let parent_wto_component = C.parentWTOComponent $ C.cfgWeakTopologicalOrdering cfg+ let call_frame_handle = CallFrameHandle (C.cfgHandle cfg) $ fmapFC C.blockInputs $ C.cfgBlockMap cfg+ modifyIORef' context_ref $ executionFeatureContextAddCallFrameContext call_frame_handle $+ CallFrameContext+ { callFrameContextFixpointStates = MapF.empty+ , callFrameContextLoopHeaders = []+ , callFrameContextCFG = cfg+ , callFrameContextParentLoop = parent_wto_component+ , callFrameContextLoopHeaderBlockIds = Set.fromList $ Map.elems parent_wto_component+ }+++initializeFixpointState ::+ (C.IsSymBackend sym bak, C.HasPtrWidth wptr, KnownNat wptr, C.HasLLVMAnn sym, ?memOpts :: C.MemOptions, ?logMessage :: String -> IO ()) =>+ bak ->+ C.GlobalVar C.Mem ->+ CallFrameHandle init ret blocks ->+ C.BlockID blocks args ->+ C.SimState p sym ext rtp (C.CrucibleLang blocks r) ('Just args) ->+ IORef (ExecutionFeatureContext sym wptr ext) ->+ IO (C.ExecutionFeatureResult p sym ext rtp)+initializeFixpointState bak mem_var call_frame_handle block_id sim_state fixpoint_state_ref = do+ let sym = C.backendGetSym bak+ assumption_frame_identifier <- C.pushAssumptionFrame bak+ ?logMessage $ "!!!SimpleLoopFixpoint: initializeFixpointState: block_id=" ++ show block_id ++ ", assumption_frame_identifier=" ++ show assumption_frame_identifier+ index_var <- W4.freshConstant sym (W4.safeSymbol "index_var") W4.knownRepr+ let mem_impl = fromJust $ C.lookupGlobal mem_var (sim_state ^. C.stateGlobals)+ let res_mem_impl = mem_impl { C.memImplHeap = C.pushStackFrameMem "fix" $ C.memImplHeap mem_impl }+ modifyIORef' fixpoint_state_ref $ callFrameContextInsert call_frame_handle block_id $ ComputeFixpoint $+ FixpointRecord+ { fixpointBlockId = block_id+ , fixpointAssumptionFrameIdentifier = assumption_frame_identifier+ , fixpointSubstitution = MapF.empty+ , fixpointRegMap = sim_state ^. (C.stateCrucibleFrame . C.frameRegs)+ , fixpointMemSubstitution = Map.empty+ , fixpointEqualitySubstitution = MapF.empty+ , fixpointIndex = index_var+ }+ modifyIORef' fixpoint_state_ref $ callFrameContextPush call_frame_handle $ Some block_id+ return $ C.ExecutionFeatureModifiedState $ C.RunningState (C.RunBlockStart block_id) $+ sim_state & C.stateGlobals %~ C.insertGlobal mem_var res_mem_impl++advanceFixpointState ::+ (C.IsSymBackend sym bak, sym ~ W4.ExprBuilder t st fs, C.HasPtrWidth wptr, KnownNat wptr, C.HasLLVMAnn sym, ?memOpts :: C.MemOptions, ?logMessage :: String -> IO ()) =>+ bak ->+ C.GlobalVar C.Mem ->+ Maybe (MapF (W4.SymExpr sym) (FixpointEntry sym) -> W4.Pred sym -> IO (MapF (W4.SymExpr sym) (W4.SymExpr sym), Maybe (W4.Pred sym))) ->+ CallFrameHandle init ret blocks ->+ C.BlockID blocks args ->+ C.SimState p sym ext rtp (C.CrucibleLang blocks r) ('Just args) ->+ IORef (ExecutionFeatureContext sym wptr ext) ->+ IO (C.ExecutionFeatureResult p sym ext rtp)++advanceFixpointState bak mem_var maybe_fixpoint_func call_frame_handle block_id sim_state fixpoint_state_ref = do+ let sym = C.backendGetSym bak+ fixpoint_state <- fromMaybe BeforeFixpoint <$> callFrameContextLookup' call_frame_handle block_id <$> readIORef fixpoint_state_ref+ case fixpoint_state of+ BeforeFixpoint -> do+ ?logMessage $ "SimpleLoopFixpoint: RunningState: BeforeFixpoint -> ComputeFixpoint"+ mapM_ (\g -> print =<< C.ppProofObligation sym g) =<< (maybe [] C.goalsToList <$> C.getProofObligations bak)+ initializeFixpointState bak mem_var call_frame_handle block_id sim_state fixpoint_state_ref++ ComputeFixpoint fixpoint_record -> do+ ?logMessage $ "SimpleLoopFixpoint: RunningState: ComputeFixpoint: " ++ show block_id+ proof_goals_and_assumptions_vars <- Set.map (mapSome $ W4.varExpr sym) <$>+ (Set.union <$> C.proofObligationsUninterpConstants bak <*> C.pathConditionUninterpConstants bak)+ (frame_assumptions, _) <- C.popAssumptionFrameAndObligations bak $ fixpointAssumptionFrameIdentifier fixpoint_record+ loop_condition <- C.assumptionsPred sym frame_assumptions++ -- widen the inductive condition+ (join_reg_map, join_substitution) <- runFixpointMonad+ (joinRegEntries sym+ (C.regMap $ fixpointRegMap fixpoint_record)+ (C.regMap $ sim_state ^. (C.stateCrucibleFrame . C.frameRegs))) $+ fixpointSubstitution fixpoint_record++ let body_mem_impl = fromJust $ C.lookupGlobal mem_var (sim_state ^. C.stateGlobals)+ let (header_mem_impl, mem_allocs, mem_writes) = dropMemStackFrame body_mem_impl+ when (C.sizeMemAllocs mem_allocs /= 0) $+ fail "SimpleLoopFixpoint: unsupported memory allocation in loop body."++ -- widen the memory+ mem_substitution_candidate <- joinMem sym header_mem_impl mem_writes++ -- check that the mem substitution always computes the same footprint on every iteration (!?!)+ mem_substitution <- if Map.null (fixpointMemSubstitution fixpoint_record)+ then return mem_substitution_candidate+ else if Map.keys mem_substitution_candidate == Map.keys (fixpointMemSubstitution fixpoint_record)+ then return $ fixpointMemSubstitution fixpoint_record+ else fail "SimpleLoopFixpoint: unsupported memory writes change"++ assumption_frame_identifier <- C.pushAssumptionFrame bak++ -- check if we are done; if we did not introduce any new variables, we don't have to widen any more+ if MapF.keys join_substitution == MapF.keys (fixpointSubstitution fixpoint_record) && Map.keys mem_substitution == Map.keys (fixpointMemSubstitution fixpoint_record)++ -- we found the fixpoint, get ready to wrap up+ then do+ ?logMessage $+ "SimpleLoopFixpoint: RunningState: ComputeFixpoint -> CheckFixpoint"++ -- we have delayed populating the main substitution map with+ -- memory variables, so we have to do that now++ header_mem_substitution <- loadMemJoinVariables bak header_mem_impl $+ fixpointMemSubstitution fixpoint_record+ body_mem_substitution <- loadMemJoinVariables bak body_mem_impl $+ fixpointMemSubstitution fixpoint_record++ -- drop variables that don't appear along some back edge+ let union_substitution' = filterSubstitution sym $+ MapF.union join_substitution $+ -- this implements zip, because the two maps have the same keys+ MapF.intersectWithKeyMaybe+ (\_k x y -> Just $ FixpointEntry{ headerValue = x, bodyValue = y })+ header_mem_substitution+ body_mem_substitution+ loop_index_linear_substitution <- loopIndexLinearSubstitution sym (fixpointIndex fixpoint_record) union_substitution'++ let union_substitution = MapF.filterWithKey+ (\variable _entry -> MapF.notMember variable loop_index_linear_substitution)+ union_substitution'+ -- try to unify widening variables that have the same values+ (normal_substitution', equality_substitution') <- uninterpretedConstantEqualitySubstitution sym union_substitution++ zero_bv <- W4.bvZero sym knownNat+ one_bv <- W4.bvOne sym knownNat+ add_index_one <- W4.bvAdd sym (fixpointIndex fixpoint_record) one_bv+ let normal_substitution = MapF.insert+ (fixpointIndex fixpoint_record)+ FixpointEntry+ { headerValue = zero_bv+ , bodyValue = add_index_one+ }+ normal_substitution'+ let equality_substitution = MapF.union equality_substitution' loop_index_linear_substitution++ ?logMessage $ "loop_index_linear_substitution: " ++ show (map (\(MapF.Pair x y) -> (W4.printSymExpr x, W4.printSymExpr y)) $ MapF.toList loop_index_linear_substitution)+ ?logMessage $ "normal_substitution: " ++ show (map (\(MapF.Pair x y) -> (W4.printSymExpr x, W4.printSymExpr $ bodyValue y)) $ MapF.toList normal_substitution)+ ?logMessage $ "equality_substitution: " ++ show (map (\(MapF.Pair x y) -> (W4.printSymExpr x, W4.printSymExpr y)) $ MapF.toList equality_substitution)++ -- unify widening variables in the register subst+ let res_reg_map = applySubstitutionRegEntries sym equality_substitution join_reg_map++ -- unify widening varialbes in the memory subst+ res_mem_impl <- storeMemJoinVariables+ bak+ (header_mem_impl { C.memImplHeap = C.pushStackFrameMem "fix" (C.memImplHeap header_mem_impl) })+ mem_substitution+ equality_substitution++ let body_values_vars = foldMap (viewSome $ Set.map (mapSome $ W4.varExpr sym) . W4.exprUninterpConstants sym . bodyValue) $+ MapF.elems normal_substitution+ let header_values_vars = foldMap (viewSome $ Set.map (mapSome $ W4.varExpr sym) . W4.exprUninterpConstants sym . headerValue) $+ MapF.elems normal_substitution+ -- let all_vars = Set.union proof_goals_and_assumptions_vars $ Set.union body_values_vars header_values_vars+ let all_vars' = Set.insert (Some $ fixpointIndex fixpoint_record) proof_goals_and_assumptions_vars+ let all_vars = Set.filter+ (\(Some variable) -> MapF.notMember variable equality_substitution)+ all_vars'+ -- let some_uninterpreted_constants = Ctx.fromList $ Set.toList all_vars+ let filtered_vars = Set.filter+ (\(Some variable) ->+ not (List.isPrefixOf "cundefined_" $ show $ W4.printSymExpr variable)+ && not (List.isPrefixOf "calign_amount" $ show $ W4.printSymExpr variable)+ && not (List.isPrefixOf "cnoSatisfyingWrite" $ show $ W4.printSymExpr variable))+ all_vars+ let some_uninterpreted_constants = Ctx.fromList $ Set.toList filtered_vars+ -- let implicit_vars = Set.filter+ -- (\(Some variable) ->+ -- not (List.isPrefixOf "creg_join_var" $ show $ W4.printSymExpr variable)+ -- && not (List.isPrefixOf "cmem_join_var" $ show $ W4.printSymExpr variable)+ -- && not (List.isPrefixOf "cundefined_" $ show $ W4.printSymExpr variable)+ -- && not (List.isPrefixOf "calign_amount" $ show $ W4.printSymExpr variable)+ -- && not (List.isPrefixOf "cnoSatisfyingWrite" $ show $ W4.printSymExpr variable))+ -- all_vars+ some_inv_pred <- case some_uninterpreted_constants of+ Some uninterpreted_constants -> do+ inv_pred <- W4.freshTotalUninterpFn+ sym+ (W4.safeSymbol "inv")+ (fmapFC W4.exprType uninterpreted_constants)+ W4.BaseBoolRepr++ loc <- W4.getCurrentProgramLoc sym++ header_inv <- W4.applySymFn sym inv_pred $+ applySubstitutionFC (fmapF headerValue normal_substitution) uninterpreted_constants+ C.addProofObligation bak $ C.LabeledPred header_inv $ C.SimError loc ""++ inv <- W4.applySymFn sym inv_pred uninterpreted_constants+ C.addAssumption bak $ C.GenericAssumption loc "inv" inv++ return $ W4.SomeSymFn inv_pred++ modifyIORef' fixpoint_state_ref $ executionFeatureContextAddInvPred some_inv_pred++ ?logMessage $+ "proof_goals_and_assumptions_vars: "+ ++ show (map (viewSome W4.printSymExpr) $ Set.toList proof_goals_and_assumptions_vars)+ ?logMessage $+ "body_values_vars: " ++ show (map (viewSome W4.printSymExpr) $ Set.toList body_values_vars)+ ?logMessage $+ "header_values_vars: " ++ show (map (viewSome W4.printSymExpr) $ Set.toList header_values_vars)+ ?logMessage $+ "uninterpreted_constants: " ++ show (map (viewSome W4.printSymExpr) $ Set.toList filtered_vars)++ modifyIORef' fixpoint_state_ref $ callFrameContextInsert call_frame_handle block_id $+ CheckFixpoint+ FixpointRecord+ { fixpointBlockId = block_id+ , fixpointAssumptionFrameIdentifier = assumption_frame_identifier+ , fixpointSubstitution = normal_substitution+ , fixpointRegMap = fixpointRegMap fixpoint_record+ , fixpointMemSubstitution = mem_substitution+ , fixpointEqualitySubstitution = equality_substitution+ , fixpointIndex = fixpointIndex fixpoint_record+ }+ some_inv_pred+ -- implicit_vars+ some_uninterpreted_constants+ loop_condition++ return $ C.ExecutionFeatureModifiedState $ C.RunningState (C.RunBlockStart block_id) $+ sim_state & (C.stateCrucibleFrame . C.frameRegs) .~ C.RegMap res_reg_map+ & C.stateGlobals %~ C.insertGlobal mem_var res_mem_impl++ else do+ ?logMessage $+ "SimpleLoopFixpoint: RunningState: ComputeFixpoint: -> ComputeFixpoint"++ -- write any new widening variables into memory state+ res_mem_impl <- storeMemJoinVariables bak+ (header_mem_impl { C.memImplHeap = C.pushStackFrameMem "fix" (C.memImplHeap header_mem_impl) })+ mem_substitution+ MapF.empty++ modifyIORef' fixpoint_state_ref $ callFrameContextInsert call_frame_handle block_id $ ComputeFixpoint+ FixpointRecord+ { fixpointBlockId = block_id+ , fixpointAssumptionFrameIdentifier = assumption_frame_identifier+ , fixpointSubstitution = join_substitution+ , fixpointRegMap = C.RegMap join_reg_map+ , fixpointMemSubstitution = mem_substitution+ , fixpointEqualitySubstitution = MapF.empty+ , fixpointIndex = fixpointIndex fixpoint_record+ }+ return $ C.ExecutionFeatureModifiedState $ C.RunningState (C.RunBlockStart block_id) $+ sim_state & (C.stateCrucibleFrame . C.frameRegs) .~ C.RegMap join_reg_map+ & C.stateGlobals %~ C.insertGlobal mem_var res_mem_impl++ CheckFixpoint fixpoint_record some_inv_pred some_uninterpreted_constants loop_condition -> do+ ?logMessage $+ "SimpleLoopFixpoint: RunningState: "+ ++ "CheckFixpoint"+ ++ " -> "+ ++ "AfterFixpoint"+ ++ ": "+ ++ show block_id++ loc <- W4.getCurrentProgramLoc sym++ -- assert that the hypothesis we made about the loop termination condition is true+ (_ :: ()) <- case (some_inv_pred, some_uninterpreted_constants) of+ (W4.SomeSymFn inv_pred, Some uninterpreted_constants)+ | Just Refl <- testEquality (W4.fnArgTypes inv_pred) (fmapFC W4.exprType uninterpreted_constants)+ , Just Refl <- testEquality (W4.fnReturnType inv_pred) W4.BaseBoolRepr -> do+ inv <- W4.applySymFn sym inv_pred $ applySubstitutionFC+ (fmapF bodyValue $ fixpointSubstitution fixpoint_record)+ uninterpreted_constants+ C.addProofObligation bak $ C.LabeledPred inv $ C.SimError loc ""+ | otherwise -> C.panic "SimpleLoopFixpoint.simpleLoopFixpoint" ["type mismatch: CheckFixpoint"]++ frame_assumptions <- C.popAssumptionFrame bak $ fixpointAssumptionFrameIdentifier fixpoint_record++ -- body_mem_substitution <- loadMemJoinVariables bak body_mem_impl $ fixpointMemSubstitution fixpoint_record+ -- let res_substitution = MapF.mapWithKey+ -- (\variable fixpoint_entry ->+ -- fixpoint_entry+ -- { bodyValue = MapF.findWithDefault (bodyValue fixpoint_entry) variable body_mem_substitution+ -- })+ -- (fixpointSubstitution fixpoint_record)+ -- ?logMessage $ "res_substitution: " ++ show (map (\(MapF.Pair x y) -> (W4.printSymExpr x, W4.printSymExpr $ bodyValue y)) $ MapF.toList res_substitution)++ -- match things up with the input function that describes the loop body behavior+ fixpoint_substitution <- case maybe_fixpoint_func of+ Just fixpoint_func -> do+ -- (fixpoint_func_substitution, maybe_fixpoint_func_condition) <- fixpoint_func res_substitution loop_condition++ correct_substitution <- traverseF+ (\fixpoint_entry -> do+ correct_body_value <- W4.substituteBoundVars sym (asBoundVarSubstitution sym $ fixpointEqualitySubstitution fixpoint_record) $ bodyValue fixpoint_entry+ return $ fixpoint_entry+ { bodyValue = correct_body_value+ })+ (fixpointSubstitution fixpoint_record)+ (fixpoint_func_substitution, maybe_fixpoint_func_condition) <- fixpoint_func correct_substitution loop_condition+ -- (fixpoint_func_substitution, maybe_fixpoint_func_condition) <- fixpoint_func (fixpointSubstitution fixpoint_record) loop_condition++ _ <- case maybe_fixpoint_func_condition of+ Just fixpoint_func_condition -> do+ bak_assumptions <- liftIO $ C.assumptionsPred sym =<< C.collectAssumptions bak+ inv_assumption <- C.assumptionPred <$> headAssumption sym frame_assumptions+ all_assumptions <- liftIO $ W4.andPred sym bak_assumptions inv_assumption+ implication <- liftIO $ W4.impliesPred sym all_assumptions fixpoint_func_condition+ modifyIORef' fixpoint_state_ref $ executionFeatureContextAddLoopFunEquivCond implication+ -- tmp_frame_id <- C.pushAssumptionFrame bak+ -- C.addProofObligation bak $ C.LabeledPred fixpoint_func_condition $ C.SimError loc ""+ -- (_, obligations) <- C.popAssumptionFrameAndObligations bak tmp_frame_id+ -- ?logMessage "before convertProofObligationsAsImplications"+ -- implications <- C.convertProofObligationsAsImplications sym obligations+ -- ?logMessage "after convertProofObligationsAsImplications"+ -- forM_ implications $ \implication ->+ -- modifyIORef' fixpoint_state_ref $ executionFeatureContextAddLoopFunEquivCond implication+ Nothing -> return ()++ ?logMessage $ "fixpoint_func_substitution: " ++ show (map (\(MapF.Pair x y) -> (W4.printSymExpr x, W4.printSymExpr y)) $ MapF.toList fixpoint_func_substitution)++ return fixpoint_func_substitution++ Nothing -> return MapF.empty++ let body_mem_impl = fromJust $ C.lookupGlobal mem_var (sim_state ^. C.stateGlobals)+ let (header_mem_impl, _mem_allocs, _mem_writes) = dropMemStackFrame body_mem_impl++ fixpoint_equality_substitution <- traverseF+ (W4.substituteBoundVars sym $ asBoundVarSubstitution sym fixpoint_substitution) $+ fixpointEqualitySubstitution fixpoint_record+ let fixpoint_equality_substitution' = MapF.union fixpoint_substitution fixpoint_equality_substitution+ let res_reg_map = C.RegMap $ applySubstitutionRegEntries sym fixpoint_equality_substitution' (C.regMap $ fixpointRegMap fixpoint_record)+ res_mem_impl <- storeMemJoinVariables bak header_mem_impl (fixpointMemSubstitution fixpoint_record) fixpoint_equality_substitution'++ (_ :: ()) <- case (some_inv_pred, some_uninterpreted_constants) of+ (W4.SomeSymFn inv_pred, Some uninterpreted_constants)+ | Just Refl <- testEquality (W4.fnArgTypes inv_pred) (fmapFC W4.exprType uninterpreted_constants)+ , Just Refl <- testEquality (W4.fnReturnType inv_pred) W4.BaseBoolRepr -> do+ inv <- W4.applySymFn sym inv_pred $ applySubstitutionFC fixpoint_substitution uninterpreted_constants+ C.addAssumption bak $ C.GenericAssumption loc "" inv+ | otherwise -> C.panic "SimpleLoopFixpoint.simpleLoopFixpoint" ["type mismatch: CheckFixpoint"]++ modifyIORef' fixpoint_state_ref $ callFrameContextInsert call_frame_handle block_id $+ AfterFixpoint+ -- fixpoint_record{ fixpointSubstitution = res_substitution }+ fixpoint_record++ return $ C.ExecutionFeatureModifiedState $ C.RunningState (C.RunBlockStart block_id) $+ sim_state & (C.stateCrucibleFrame . C.frameRegs) .~ res_reg_map+ & C.stateGlobals %~ C.insertGlobal mem_var res_mem_impl++ AfterFixpoint{} -> do+ ?logMessage $ "SimpleLoopFixpoint: RunningState: AfterFixpoint -> ComputeFixpoint"+ initializeFixpointState bak mem_var call_frame_handle block_id sim_state fixpoint_state_ref+++handleSymbolicBranch ::+ (C.IsSymBackend sym bak, C.HasPtrWidth wptr, KnownNat wptr, C.HasLLVMAnn sym, ?memOpts :: C.MemOptions, ?logMessage :: String -> IO ()) =>+ bak ->+ CallFrameHandle init ret blocks ->+ C.BlockID blocks tp ->+ W4.Pred sym ->+ C.PausedFrame p sym ext rtp (C.CrucibleLang blocks r) ->+ C.PausedFrame p sym ext rtp (C.CrucibleLang blocks r) ->+ Maybe (C.Some (C.BlockID blocks)) ->+ Maybe (C.Some (C.BlockID blocks)) ->+ C.SimState p sym ext rtp (C.CrucibleLang blocks r) ('Just args) ->+ IORef (ExecutionFeatureContext sym wptr ext) ->+ IO (C.ExecutionFeatureResult p sym ext rtp)+handleSymbolicBranch bak call_frame_handle loop_block_id branch_condition true_frame false_frame true_frame_parent_loop_id false_frame_parent_loop_id sim_state fixpoint_state_ref = do+ let sym = C.backendGetSym bak++ (loop_condition, inside_loop_frame, outside_loop_frame) <-+ if true_frame_parent_loop_id == Just (C.Some loop_block_id)+ then+ return (branch_condition, true_frame, false_frame)+ else if false_frame_parent_loop_id == Just (C.Some loop_block_id)+ then do+ not_branch_condition <- W4.notPred sym branch_condition+ return (not_branch_condition, false_frame, true_frame)+ else+ fail $ "unsupported loop: loop header block id " ++ show loop_block_id ++ " true frame parent loop id " ++ show true_frame_parent_loop_id ++ " false frame parent loop id " ++ show false_frame_parent_loop_id++ Just fixpoint_state <- callFrameContextLookup' call_frame_handle loop_block_id <$> readIORef fixpoint_state_ref+ (condition, frame) <- case fixpoint_state of+ BeforeFixpoint -> C.panic "SimpleLoopFixpoint.simpleLoopFixpoint:" ["BeforeFixpoint"]++ ComputeFixpoint{} -> do+ -- continue in the loop+ ?logMessage "SimpleLoopFixpoint: SymbolicBranchState: ComputeFixpoint"+ return (loop_condition, inside_loop_frame)++ CheckFixpoint fixpoint_record some_inv_pred some_uninterpreted_constants _ -> do+ -- continue in the loop+ ?logMessage "SimpleLoopFixpoint: SymbolicBranchState: CheckFixpoint"+ modifyIORef' fixpoint_state_ref $ callFrameContextInsert call_frame_handle loop_block_id $+ CheckFixpoint fixpoint_record some_inv_pred some_uninterpreted_constants loop_condition+ return (loop_condition, inside_loop_frame)++ AfterFixpoint{} -> do+ -- break out of the loop+ ?logMessage "SimpleLoopFixpoint: SymbolicBranchState: AfterFixpoint"+ modifyIORef' fixpoint_state_ref $ callFrameContextPop call_frame_handle+ not_loop_condition <- W4.notPred sym loop_condition+ return (not_loop_condition, outside_loop_frame)++ loc <- W4.getCurrentProgramLoc sym+ C.addAssumption bak $ C.BranchCondition loc (C.pausedLoc frame) condition+ C.ExecutionFeatureNewState <$>+ runReaderT+ (C.resumeFrame (C.forgetPostdomFrame frame) $ sim_state ^. (C.stateTree . C.actContext))+ sim_state+++data SomeCallFrameHandle ret blocks = forall init . SomeCallFrameHandle (CallFrameHandle init ret blocks)++callFrameHandle :: C.CallFrame sym ext blocks ret ctx -> SomeCallFrameHandle ret blocks+callFrameHandle C.CallFrame { _frameCFG = g } =+ SomeCallFrameHandle $ CallFrameHandle (C.cfgHandle g) $ fmapFC C.blockInputs $ C.cfgBlockMap g++data MaybePausedFrameTgtId f where+ JustPausedFrameTgtId :: C.Some (C.BlockID b) -> MaybePausedFrameTgtId (C.CrucibleLang b r)+ NothingPausedFrameTgtId :: MaybePausedFrameTgtId f++pausedFrameTgtId :: C.PausedFrame p sym ext rtp f -> MaybePausedFrameTgtId f+pausedFrameTgtId C.PausedFrame{ resume = resume } = case resume of+ C.ContinueResumption (C.ResolvedJump tgt_id _) -> JustPausedFrameTgtId $ C.Some tgt_id+ C.CheckMergeResumption (C.ResolvedJump tgt_id _) -> JustPausedFrameTgtId $ C.Some tgt_id+ _ -> NothingPausedFrameTgtId+++applySubstitutionFC :: (OrdF k, FunctorFC f) => MapF k k -> f k l -> f k l+applySubstitutionFC substitution = fmapFC $ findWithDefaultKey substitution++findWithDefaultKey :: forall a (k :: a -> Type) tp . OrdF k => MapF k k -> k tp -> k tp+findWithDefaultKey substitution key = MapF.findWithDefault key key substitution++asBoundVarSubstitution :: W4.IsSymExprBuilder sym => sym -> MapF (W4.SymExpr sym) a -> MapF (W4.BoundVar sym) a+asBoundVarSubstitution sym =+ MapF.fromList . mapMaybe (\(MapF.Pair k_expr v) -> fmap (\k_var -> MapF.Pair k_var v) $ asBoundVar sym k_expr) . MapF.toList++asBoundVar :: W4.IsSymExprBuilder sym => sym -> W4.SymExpr sym tp -> Maybe (W4.BoundVar sym tp)+asBoundVar sym expr = case Set.toList (W4.exprUninterpConstants sym expr) of+ [Some var]+ | Just Refl <- testEquality expr (W4.varExpr sym var) ->+ Just var+ _ -> Nothing++headAssumption :: sym -> C.Assumptions sym -> IO (C.CrucibleAssumption (W4.SymExpr sym))+headAssumption sym = \case+ C.SingleAssumption a -> return a+ C.ManyAssumptions (x Seq.:<| _) -> headAssumption sym x+ _ -> fail "SimpleLoopFixpoint.headAssumption: empty assumptions"
src/Lang/Crucible/LLVM/SimpleLoopInvariant.hs view
@@ -518,7 +518,7 @@ C.Err _ -> return def C.NoErr p v -> do v' <- C.unpackMemValue sym (C.LLVMPointerRepr w) v- p0 <- W4.natEq sym (C.llvmPointerBlock v') =<< W4.natLit sym 0+ p0 <- C.ptrIsBv sym v' p' <- W4.andPred sym p p0 W4.bvIte sym p' (C.llvmPointerOffset v') def
src/Lang/Crucible/LLVM/SymIO.hs view
@@ -401,24 +401,23 @@ openFile :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMFileSystem wptr- -> LLVMOverride p sym+ -> LLVMOverride p sym ext (EmptyCtx ::> LLVMPointerType wptr ::> BVType 32) (BVType 32) openFile fsVars = [llvmOvr| i32 @open( i8*, i32 ) |] -- TODO add mode support by making this a varargs function- (\memOps bak args -> uncurryAssignment (callOpenFile bak memOps fsVars) args)+ (\memOps args -> uncurryAssignment (callOpenFile memOps fsVars) args) callOpenFile ::- (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) =>- bak ->+ (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType 32) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType 32))-callOpenFile _bak memOps fsVars filename_ptr _flags =+callOpenFile memOps fsVars filename_ptr _flags = do fileIdent <- loadFileIdent memOps (regValue filename_ptr) SymIO.openFile (llvmFileSystem fsVars) fileIdent $ \case Left SymIO.FileNotFound -> returnIOError32@@ -427,22 +426,21 @@ closeFile :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMFileSystem wptr- -> LLVMOverride p sym+ -> LLVMOverride p sym ext (EmptyCtx ::> BVType 32) (BVType 32) closeFile fsVars = [llvmOvr| i32 @close( i32 ) |]- (\memOps bak args -> uncurryAssignment (callCloseFile bak memOps fsVars) args)+ (\memOps args -> uncurryAssignment (callCloseFile memOps fsVars) args) callCloseFile ::- (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr) =>- bak ->+ (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (BVType 32) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType 32))-callCloseFile bak _memOps fsVars filedesc =- do let sym = backendGetSym bak+callCloseFile _memOps fsVars filedesc =+ do sym <- getSymInterface lookupFileHandle fsVars (regValue filedesc) emptyRegMap $ \case Just fileHandle -> \_ -> SymIO.closeFileHandle (llvmFileSystem fsVars) fileHandle $ \case@@ -453,36 +451,36 @@ readFileHandle :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => LLVMFileSystem wptr- -> LLVMOverride p sym+ -> LLVMOverride p sym ext (EmptyCtx ::> BVType 32 ::> LLVMPointerType wptr ::> BVType wptr) (BVType wptr) readFileHandle fsVars = [llvmOvr| ssize_t @read( i32, i8*, size_t ) |]- (\memOps bak args -> uncurryAssignment (callReadFileHandle bak memOps fsVars) args)+ (\memOps args -> uncurryAssignment (callReadFileHandle memOps fsVars) args) callReadFileHandle ::- (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr) =>- bak ->+ (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr) => GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (BVType 32) -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType wptr))-callReadFileHandle bak memOps fsVars filedesc buf count =- do let sym = backendGetSym bak+callReadFileHandle memOps fsVars filedesc buf count =+ do sym <- getSymInterface let args = Empty :> filedesc :> buf :> count lookupFileHandle fsVars (regValue filedesc) (RegMap args) $ \case Just fileHandle -> \(RegMap (Empty :> _ :> buffer_ptr :> size)) -> SymIO.readChunk (llvmFileSystem fsVars) fileHandle (regValue size) $ \case Left SymIO.FileHandleClosed -> returnIOError Right (chunk, bytesRead) -> do- modifyGlobal memOps $ \mem -> liftIO $ do- chunkArray <- SymIO.chunkToArray sym (W4.BaseBVRepr PtrWidth) chunk- mem' <- doArrayStore bak mem (regValue buffer_ptr) noAlignment chunkArray bytesRead- return (bytesRead, mem')+ ovrWithBackend $ \bak ->+ modifyGlobal memOps $ \mem -> liftIO $ do+ chunkArray <- SymIO.chunkToArray sym (W4.BaseBVRepr PtrWidth) chunk+ mem' <- doArrayStore bak mem (regValue buffer_ptr) noAlignment chunkArray bytesRead+ return (bytesRead, mem') Nothing -> \_ -> returnIOError -- | If the write is to a concrete FD for which we have an associated 'IO.Handle', mirror the write to that Handle@@ -523,34 +521,34 @@ writeFileHandle :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => LLVMFileSystem wptr- -> LLVMOverride p sym+ -> LLVMOverride p sym ext (EmptyCtx ::> BVType 32 ::> LLVMPointerType wptr ::> BVType wptr) (BVType wptr) writeFileHandle fsVars = [llvmOvr| ssize_t @write( i32, i8*, size_t ) |]- (\memOps bak args -> uncurryAssignment (callWriteFileHandle bak memOps fsVars) args)+ (\memOps args -> uncurryAssignment (callWriteFileHandle memOps fsVars) args) callWriteFileHandle ::- (IsSymBackend sym bak, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) =>- bak ->+ (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, ?memOpts :: MemOptions) => GlobalVar Mem -> LLVMFileSystem wptr -> RegEntry sym (BVType 32) -> RegEntry sym (LLVMPointerType wptr) -> RegEntry sym (BVType wptr) -> OverrideSim p sym ext rtp args ret (RegValue sym (BVType wptr))-callWriteFileHandle bak memOps fsVars filedesc buf count =+callWriteFileHandle memOps fsVars filedesc buf count = do let args = Empty :> filedesc :> buf :> count lookupFileHandle fsVars (regValue filedesc) (RegMap args) $ \case Just fileHandle -> \(RegMap (Empty :> _ :> buffer_ptr :> size)) -> do mem <- readGlobal memOps- chunk <- liftIO $ chunkFromMemory bak mem (regValue buffer_ptr)- doConcreteWrite (llvmFilePointerRepr fsVars) (llvmHandles fsVars) (regValue filedesc) chunk size- SymIO.writeChunk (llvmFileSystem fsVars) fileHandle chunk (regValue size) $ \case- Left SymIO.FileHandleClosed -> returnIOError- Right bytesWritten -> return bytesWritten+ ovrWithBackend $ \bak -> do+ chunk <- liftIO $ chunkFromMemory bak mem (regValue buffer_ptr)+ doConcreteWrite (llvmFilePointerRepr fsVars) (llvmHandles fsVars) (regValue filedesc) chunk size+ SymIO.writeChunk (llvmFileSystem fsVars) fileHandle chunk (regValue size) $ \case+ Left SymIO.FileHandleClosed -> returnIOError+ Right bytesWritten -> return bytesWritten Nothing -> \_ -> returnIOError -- | The file handling overrides@@ -559,7 +557,7 @@ symio_overrides :: (IsSymInterface sym, HasLLVMAnn sym, HasPtrWidth wptr, wptr ~ ArchWidth arch, ?memOpts :: MemOptions) => LLVMFileSystem wptr- -> [OverrideTemplate p sym arch rtp l a]+ -> [OverrideTemplate p sym ext arch] symio_overrides fs = [ basic_llvm_override $ openFile fs , basic_llvm_override $ closeFile fs
src/Lang/Crucible/LLVM/Translation/Expr.hs view
@@ -101,7 +101,6 @@ import Lang.Crucible.Syntax import Lang.Crucible.Types -import What4.InterpretedFloatingPoint (X86_80Val(..)) ------------------------------------------------------------------------- -- LLVMExpr
src/Lang/Crucible/LLVM/Translation/Instruction.hs view
@@ -1073,6 +1073,7 @@ continueLambda c_label (branch cond bv_label ptr_label) atomicRWOp ::+ forall s arch ret. L.AtomicRWOp -> LLVMExpr s arch -> LLVMExpr s arch ->@@ -1083,26 +1084,133 @@ | Just Refl <- testEquality w w' -> do xbv <- pointerAsBitvectorExpr w x' ybv <- pointerAsBitvectorExpr w y'- let newval = case op of- L.AtomicXchg -> ybv- L.AtomicAdd -> app $ BVAdd w xbv ybv- L.AtomicSub -> app $ BVSub w xbv ybv- L.AtomicAnd -> app $ BVAnd w xbv ybv- L.AtomicNand -> app $ BVNot w $ app $ BVAnd w xbv ybv- L.AtomicOr -> app $ BVOr w xbv ybv- L.AtomicXor -> app $ BVXor w xbv ybv- L.AtomicMax -> app $ BVSMax w xbv ybv- L.AtomicMin -> app $ BVSMin w xbv ybv- L.AtomicUMax -> app $ BVUMax w xbv ybv- L.AtomicUMin -> app $ BVUMin w xbv ybv+ newval <- bvOp w xbv ybv return $ BaseExpr (LLVMPointerRepr w) $ BitvectorAsPointerExpr w newval + (Scalar _archProxy (FloatRepr fi) xf, Scalar _archPrxy' (FloatRepr fi') yf)+ | Just Refl <- testEquality fi fi'+ -> do newval <- floatingOp fi xf yf+ return $ BaseExpr (FloatRepr fi) newval+ _ -> fail $ unlines [ "atomicRW operation on incompatible values" , "Operation: " ++ show op , "Value 1: " ++ show x , "Value 2: " ++ show y ]+ where+ -- Translate an atomic operation over bitvector values, respecting the+ -- semantics described in this part of the LLVM Language Reference Manual:+ -- https://releases.llvm.org/16.0.0/docs/LangRef.html#id229+ --+ -- Note that `xbv` corresponds to `*ptr` and `ybv` corresponds to `val` in+ -- the Reference Manual.+ bvOp ::+ forall w.+ (1 <= w) =>+ NatRepr w ->+ Expr LLVM s (BVType w) ->+ Expr LLVM s (BVType w) ->+ LLVMGenerator s arch ret (Expr LLVM s (BVType w))+ bvOp w xbv ybv =+ case op of+ L.AtomicXchg -> pure ybv+ L.AtomicAdd -> pure $ app $ BVAdd w xbv ybv+ L.AtomicSub -> pure $ app $ BVSub w xbv ybv+ L.AtomicAnd -> pure $ app $ BVAnd w xbv ybv+ L.AtomicNand -> pure $ app $ BVNot w $ app $ BVAnd w xbv ybv+ L.AtomicOr -> pure $ app $ BVOr w xbv ybv+ L.AtomicXor -> pure $ app $ BVXor w xbv ybv+ L.AtomicMax -> pure $ app $ BVSMax w xbv ybv+ L.AtomicMin -> pure $ app $ BVSMin w xbv ybv+ L.AtomicUMax -> pure $ app $ BVUMax w xbv ybv+ L.AtomicUMin -> pure $ app $ BVUMin w xbv ybv+ L.AtomicUIncWrap ->+ -- This is the same thing as+ --+ -- (*ptr u>= val) ? 0 : (*ptr + 1)+ --+ -- from the LLVM semantics, but with a double-negated condition to+ -- account for the Crucible CFG language not having a BVUge operation+ -- (only BVUlt).+ let c = app $ Not $ app $ BVUlt w xbv ybv -- ~(*ptr u< val)+ t = zero+ f = app $ BVAdd w xbv one in+ pure $ app $ BVIte c w t f+ L.AtomicUDecWrap ->+ -- This is the same thing as+ --+ -- ((*ptr == 0) || (*ptr u> val)) ? val : (*ptr - 1)+ --+ -- from the LLVM semantics, but with a double-negated condition to+ -- account for the Crucible CFG language not having a BVUgt operation+ -- (only BVUle).+ let c1 = app $ BVEq w xbv zero+ c2 = app $ Not $ app $ BVUle w xbv ybv -- ~(*ptr u<= val)+ c = app $ Or c1 c2+ t = xbv+ f = app $ BVSub w xbv one in+ pure $ app $ BVIte c w t f + L.AtomicFAdd -> nonBvError+ L.AtomicFSub -> nonBvError+ L.AtomicFMax -> nonBvError+ L.AtomicFMin -> nonBvError+ where+ zero, one :: Expr LLVM s (BVType w)+ zero = app $ BVLit w $ BV.zero w+ one = app $ BVLit w $ BV.one w++ nonBvError :: forall a. LLVMGenerator s arch ret a+ nonBvError =+ reportError $ fromString $ unwords+ [ "Invalid atomic bitvector operation"+ , "Operation: " ++ show op+ , "Value 1: " ++ show xbv+ , "Value 2: " ++ show ybv+ ]++ -- Translate an atomic operation over floating-point values, respecting the+ -- semantics described in this part of the LLVM Language Reference Manual:+ -- https://releases.llvm.org/16.0.0/docs/LangRef.html#id229+ --+ -- Note that `xf` corresponds to `*ptr` and `yf` corresponds to `val` in the+ -- Reference Manual.+ floatingOp ::+ forall fi.+ FloatInfoRepr fi ->+ Expr LLVM s (FloatType fi) ->+ Expr LLVM s (FloatType fi) ->+ LLVMGenerator s arch ret (Expr LLVM s (FloatType fi))+ floatingOp fi xf yf =+ case op of+ L.AtomicXchg -> pure yf+ L.AtomicFAdd -> pure $ app $ FloatAdd fi RNE xf yf+ L.AtomicFSub -> pure $ app $ FloatSub fi RNE xf yf+ L.AtomicFMax -> pure $ app $ FloatMax fi xf yf+ L.AtomicFMin -> pure $ app $ FloatMin fi xf yf++ L.AtomicAdd -> nonFloatingError+ L.AtomicSub -> nonFloatingError+ L.AtomicAnd -> nonFloatingError+ L.AtomicNand -> nonFloatingError+ L.AtomicOr -> nonFloatingError+ L.AtomicXor -> nonFloatingError+ L.AtomicMax -> nonFloatingError+ L.AtomicMin -> nonFloatingError+ L.AtomicUMax -> nonFloatingError+ L.AtomicUMin -> nonFloatingError+ L.AtomicUIncWrap -> nonFloatingError+ L.AtomicUDecWrap -> nonFloatingError+ where+ nonFloatingError :: forall a. LLVMGenerator s arch ret a+ nonFloatingError =+ reportError $ fromString $ unwords+ [ "Invalid atomic floating-point operation"+ , "Operation: " ++ show op+ , "Value 1: " ++ show xf+ , "Value 2: " ++ show yf+ ]+ floatingCompare :: L.FCmpOp -> MemType ->@@ -1713,6 +1821,9 @@ ptr' <- transTypedValue ptr case valTy of IntType _ -> pure ()+ FloatType -> pure ()+ DoubleType -> pure ()+ X86_FP80Type -> pure () _ -> fail $ unwords ["Invalid argument type on atomicrw, expected integer type", show ptr] llvmTypeAsRepr valTy $ \expectTy ->@@ -1942,6 +2053,8 @@ , "llvm.dbg.declare" , "llvm.dbg.addr" , "llvm.dbg.value"+ , "llvm.dbg.assign" -- Added in LLVM 16+ , "llvm.experimental.noalias.scope.decl" -- Added in LLVM 12 , "llvm.lifetime.start" , "llvm.lifetime.start.p0" , "llvm.lifetime.start.p0i8"
src/Lang/Crucible/LLVM/Utils.hs view
@@ -1,3 +1,7 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeOperators #-}+ ------------------------------------------------------------------------ -- | -- Module : Lang.Crucible.LLVM.Utils@@ -7,9 +11,35 @@ -- Maintainer : Rob Dockins <rdockins@galois.com> -- Stability : provisional -------------------------------------------------------------------------module Lang.Crucible.LLVM.Utils (applyUnless) where+module Lang.Crucible.LLVM.Utils+ ( applyUnless+ , sextendBVTo+ ) where +import What4.Interface++import Lang.Crucible.Backend+import Lang.Crucible.Panic (panic)+ -- | If the first argument is 'False', apply the second argument to the third. -- Otherwise, simply return the third argument. applyUnless :: Applicative f => Bool -> (a -> f a) -> a -> f a applyUnless b f x = if b then pure x else f x++-- | Convert a 'SymBV' value of width @w@ to width @w'@, performing sign+-- extension or truncation as needed.+sextendBVTo :: (1 <= w, 1 <= w', IsSymInterface sym)+ => sym+ -> NatRepr w+ -> NatRepr w'+ -> SymExpr sym (BaseBVType w)+ -> IO (SymExpr sym (BaseBVType w'))+sextendBVTo sym w w' x+ | Just Refl <- testEquality w w' = return x+ | Just LeqProof <- testLeq (incNat w) w' = bvSext sym w' x+ | Just LeqProof <- testLeq (incNat w') w = bvTrunc sym w' x+ | otherwise = panic "sextendBVTo"+ [ "Impossible widths!"+ , show w+ , show w'+ ]
test/TestMemory.hs view
@@ -134,7 +134,7 @@ i <- What4.freshConstant sym (userSymbol' "i") $ What4.BaseBVRepr ?ptrWidth ptr_i <- ptrAdd sym ?ptrWidth base_ptr =<< What4.bvMul sym stride i- ptr_i' <- ptrAdd sym ?ptrWidth ptr_i =<< What4.bvLit sym ?ptrWidth (BV.one ?ptrWidth)+ ptr_i' <- ptrAdd sym ?ptrWidth ptr_i =<< What4.bvOne sym ?ptrWidth zero_bv <- What4.bvLit sym (knownNat @8) (BV.zero knownNat) mem3 <-@@ -149,7 +149,7 @@ j <- What4.freshConstant sym (userSymbol' "j") $ What4.BaseBVRepr ?ptrWidth ptr_j <- ptrAdd sym ?ptrWidth base_ptr =<< What4.bvMul sym stride j- ptr_j' <- ptrAdd sym ?ptrWidth ptr_j =<< What4.bvLit sym ?ptrWidth (BV.one ?ptrWidth)+ ptr_j' <- ptrAdd sym ?ptrWidth ptr_j =<< What4.bvOne sym ?ptrWidth at_j_val <- projectLLVM_bv bak =<< doLoad bak mem4 ptr_j byte_storage_type ptr_byte_repr noAlignment@@ -329,7 +329,7 @@ assume bak =<< What4.bvUlt sym len =<< What4.bvLit sym ?ptrWidth (BV.mkBV ?ptrWidth 1024) mem3 <- LLVMMem.doMemcpy bak ?ptrWidth mem2 False dst_ptr src_base_ptr len - zero_bv <- What4.bvLit sym ?ptrWidth $ BV.zero ?ptrWidth+ zero_bv <- What4.bvZero sym ?ptrWidth expected_arr <- What4.arrayCopy sym dst_arr i src_arr zero_bv len expected_val <- What4.arrayLookup sym expected_arr $ Ctx.singleton i