From d395484ebddb8e43d717d31a8c3d055bb6d0e758 Mon Sep 17 00:00:00 2001 From: Rob Dockins Date: Thu, 9 May 2019 18:09:43 -0700 Subject: [PATCH 1/3] Speed up the override registration phase by prefiltering possible overrides first. This significantly reduces the amount of startup time that is consumed by installing overrides, especially C++ overrides that perform name demangling. Each override that wants to be registered now provides a "matcher" which examines the name of a symbol for an approximate test as to weather this override applies. These can either be exact matches, prefix matches, or substring matches. Any override that passes the prefilter test is considered in order, as before, to determine more precicely if it applies. On one modestly-sized example, this reduced overall verification time from 105 seconds to 32 seconds. The algorithm used here for pre-filtering is quite naive, so additional improvements are perhaps possible. However, at the momemnt, startup time is dominated by parsing the bitcode file itself. --- .../src/Lang/Crucible/LLVM/Intrinsics.hs | 179 +++++++++++------- .../Lang/Crucible/LLVM/Intrinsics/Common.hs | 38 +++- .../Lang/Crucible/LLVM/Intrinsics/Libcxx.hs | 164 ++++++++-------- 3 files changed, 231 insertions(+), 150 deletions(-) diff --git a/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics.hs b/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics.hs index b2f32c284..4ae99e82b 100644 --- a/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics.hs +++ b/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics.hs @@ -49,8 +49,10 @@ import Control.Monad.Reader import Control.Monad.State import Control.Monad.Trans.Maybe import Data.Foldable (asum) +import Data.List (stripPrefix, tails, isPrefixOf) import qualified Text.LLVM.AST as L +import qualified ABI.Itanium as ABI import qualified Data.Parameterized.Map as MapF import What4.Interface @@ -86,17 +88,50 @@ register_llvm_overrides llvmModule llvmctx = register_llvm_define_overrides llvmModule llvmctx >>= register_llvm_declare_overrides llvmModule + +-- | Filter the initial list of templates to only those that could +-- possibly match the given declaration based on straightforward, +-- relatively cheap string tests on the name of the declaration. +-- +-- Any remaining templates will then examine the declaration in +-- 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] -> + 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 ] + + -- | Helper function for registering overrides register_llvm_overrides_ :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => LLVMContext arch -> - [RegOverrideM p sym arch rtp l a ()] -> + [OverrideTemplate p sym arch rtp l a] -> [L.Declare] -> OverrideSim p sym (LLVM arch) rtp l a (LLVMContext arch) register_llvm_overrides_ llvmctx acts decls = flip execStateT llvmctx $ forM_ decls $ \decl -> - runMaybeT (flip runReaderT decl $ asum acts) >> return () + 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) $ asum (map overrideTemplateAction acts')) >> return () register_llvm_define_overrides :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => @@ -131,95 +166,95 @@ register_llvm_declare_overrides llvmModule llvmctx = -- | Register overrides for declared-but-not-defined functions declare_overrides :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch, ?lc :: TypeContext) => - [RegOverrideM p sym arch rtp l a ()] + [OverrideTemplate p sym arch rtp l a] declare_overrides = - [ register_llvm_override LLVM.llvmLifetimeStartOverride - , register_llvm_override LLVM.llvmLifetimeEndOverride - , register_llvm_override (LLVM.llvmLifetimeOverrideOverload "start" (knownNat @8)) - , register_llvm_override (LLVM.llvmLifetimeOverrideOverload "end" (knownNat @8)) - , register_llvm_override (LLVM.llvmInvariantStartOverride (knownNat @8)) - , register_llvm_override (LLVM.llvmInvariantEndOverride (knownNat @8)) - , register_llvm_override (LLVM.llvmExpectOverride (knownNat @64)) - , register_llvm_override LLVM.llvmAssumeOverride - - , register_llvm_override LLVM.llvmMemcpyOverride_8_8_32 - , register_llvm_override LLVM.llvmMemcpyOverride_8_8_32_noalign - , register_llvm_override LLVM.llvmMemcpyOverride_8_8_64 - , register_llvm_override LLVM.llvmMemcpyOverride_8_8_64_noalign - - , register_llvm_override LLVM.llvmMemmoveOverride_8_8_32 - , register_llvm_override LLVM.llvmMemmoveOverride_8_8_32_noalign - , register_llvm_override LLVM.llvmMemmoveOverride_8_8_64 - , register_llvm_override LLVM.llvmMemmoveOverride_8_8_64_noalign - - , register_llvm_override LLVM.llvmMemsetOverride_8_32 - , register_llvm_override LLVM.llvmMemsetOverride_8_32_noalign - , register_llvm_override LLVM.llvmMemsetOverride_8_64 - , register_llvm_override LLVM.llvmMemsetOverride_8_64_noalign - - , register_llvm_override LLVM.llvmObjectsizeOverride_32 - , register_llvm_override LLVM.llvmObjectsizeOverride_64 - - , register_llvm_override LLVM.llvmObjectsizeOverride_32' - , register_llvm_override LLVM.llvmObjectsizeOverride_64' - - , register_llvm_override LLVM.llvmStacksave - , register_llvm_override LLVM.llvmStackrestore - - , register_1arg_polymorphic_override "llvm.ctlz" + [ 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.llvmInvariantStartOverride (knownNat @8)) + , basic_llvm_override (LLVM.llvmInvariantEndOverride (knownNat @8)) + , basic_llvm_override (LLVM.llvmExpectOverride (knownNat @64)) + , basic_llvm_override LLVM.llvmAssumeOverride + + , basic_llvm_override LLVM.llvmMemcpyOverride_8_8_32 + , basic_llvm_override LLVM.llvmMemcpyOverride_8_8_32_noalign + , basic_llvm_override LLVM.llvmMemcpyOverride_8_8_64 + , basic_llvm_override LLVM.llvmMemcpyOverride_8_8_64_noalign + + , basic_llvm_override LLVM.llvmMemmoveOverride_8_8_32 + , basic_llvm_override LLVM.llvmMemmoveOverride_8_8_32_noalign + , basic_llvm_override LLVM.llvmMemmoveOverride_8_8_64 + , basic_llvm_override LLVM.llvmMemmoveOverride_8_8_64_noalign + + , basic_llvm_override LLVM.llvmMemsetOverride_8_32 + , basic_llvm_override LLVM.llvmMemsetOverride_8_32_noalign + , basic_llvm_override LLVM.llvmMemsetOverride_8_64 + , basic_llvm_override LLVM.llvmMemsetOverride_8_64_noalign + + , basic_llvm_override LLVM.llvmObjectsizeOverride_32 + , basic_llvm_override LLVM.llvmObjectsizeOverride_64 + + , basic_llvm_override LLVM.llvmObjectsizeOverride_32' + , basic_llvm_override LLVM.llvmObjectsizeOverride_64' + + , basic_llvm_override LLVM.llvmStacksave + , basic_llvm_override LLVM.llvmStackrestore + + , polymorphic1_llvm_override "llvm.ctlz" (\w -> SomeLLVMOverride (LLVM.llvmCtlz w)) - , register_1arg_polymorphic_override "llvm.cttz" + , polymorphic1_llvm_override "llvm.cttz" (\w -> SomeLLVMOverride (LLVM.llvmCttz w)) - , register_1arg_polymorphic_override "llvm.ctpop" + , polymorphic1_llvm_override "llvm.ctpop" (\w -> SomeLLVMOverride (LLVM.llvmCtpop w)) - , register_1arg_polymorphic_override "llvm.bitreverse" + , polymorphic1_llvm_override "llvm.bitreverse" (\w -> SomeLLVMOverride (LLVM.llvmBitreverse w)) - , register_llvm_override (LLVM.llvmBSwapOverride (knownNat @2)) -- 16 = 2 * 8 - , register_llvm_override (LLVM.llvmBSwapOverride (knownNat @4)) -- 32 = 4 * 8 - , register_llvm_override (LLVM.llvmBSwapOverride (knownNat @6)) -- 48 = 6 * 8 - , register_llvm_override (LLVM.llvmBSwapOverride (knownNat @8)) -- 64 = 8 * 8 - , register_llvm_override (LLVM.llvmBSwapOverride (knownNat @10)) -- 80 = 10 * 8 - , register_llvm_override (LLVM.llvmBSwapOverride (knownNat @12)) -- 96 = 12 * 8 - , register_llvm_override (LLVM.llvmBSwapOverride (knownNat @14)) -- 112 = 14 * 8 - , register_llvm_override (LLVM.llvmBSwapOverride (knownNat @16)) -- 128 = 16 * 8 + , 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 - , register_1arg_polymorphic_override "llvm.sadd.with.overflow" + , polymorphic1_llvm_override "llvm.sadd.with.overflow" (\w -> SomeLLVMOverride (LLVM.llvmSaddWithOverflow w)) - , register_1arg_polymorphic_override "llvm.uadd.with.overflow" + , polymorphic1_llvm_override "llvm.uadd.with.overflow" (\w -> SomeLLVMOverride (LLVM.llvmUaddWithOverflow w)) - , register_1arg_polymorphic_override "llvm.ssub.with.overflow" + , polymorphic1_llvm_override "llvm.ssub.with.overflow" (\w -> SomeLLVMOverride (LLVM.llvmSsubWithOverflow w)) - , register_1arg_polymorphic_override "llvm.usub.with.overflow" + , polymorphic1_llvm_override "llvm.usub.with.overflow" (\w -> SomeLLVMOverride (LLVM.llvmUsubWithOverflow w)) - , register_1arg_polymorphic_override "llvm.smul.with.overflow" + , polymorphic1_llvm_override "llvm.smul.with.overflow" (\w -> SomeLLVMOverride (LLVM.llvmSmulWithOverflow w)) - , register_1arg_polymorphic_override "llvm.umul.with.overflow" + , polymorphic1_llvm_override "llvm.umul.with.overflow" (\w -> SomeLLVMOverride (LLVM.llvmUmulWithOverflow w)) -- C standard library functions - , register_llvm_override Libc.llvmAssertRtnOverride - , register_llvm_override Libc.llvmMemcpyOverride - , register_llvm_override Libc.llvmMemcpyChkOverride - , register_llvm_override Libc.llvmMemmoveOverride - , register_llvm_override Libc.llvmMemsetOverride - , register_llvm_override Libc.llvmMemsetChkOverride - , register_llvm_override Libc.llvmMallocOverride - , register_llvm_override Libc.llvmCallocOverride - , register_llvm_override Libc.llvmFreeOverride - , register_llvm_override Libc.llvmReallocOverride - , register_llvm_override Libc.llvmStrlenOverride - , register_llvm_override Libc.llvmPrintfOverride - , register_llvm_override Libc.llvmPrintfChkOverride - , register_llvm_override Libc.llvmPutsOverride - , register_llvm_override Libc.llvmPutCharOverride + , basic_llvm_override Libc.llvmAssertRtnOverride + , 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 -- C++ standard library functions , Libcxx.register_cpp_override Libcxx.endlOverride -- Some architecture-dependent intrinsics - , register_llvm_override LLVM.llvmX86_SSE2_storeu_dq - , register_llvm_override LLVM.llvmX86_pclmulqdq + , basic_llvm_override LLVM.llvmX86_SSE2_storeu_dq + , basic_llvm_override LLVM.llvmX86_pclmulqdq ] @@ -227,7 +262,7 @@ declare_overrides = -- function has a definition define_overrides :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch, ?lc :: TypeContext) => - [RegOverrideM p sym arch rtp l a ()] + [OverrideTemplate p sym arch rtp l a] define_overrides = [ Libcxx.register_cpp_override Libcxx.putToOverride12 , Libcxx.register_cpp_override Libcxx.putToOverride9 diff --git a/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Common.hs b/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Common.hs index 84e1135f1..70e23715b 100644 --- a/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Common.hs +++ b/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Common.hs @@ -21,6 +21,8 @@ module Lang.Crucible.LLVM.Intrinsics.Common , SomeLLVMOverride(..) , RegOverrideM , llvmSizeT + , OverrideTemplate(..) + , TemplateMatcher(..) -- ** LLVMContext , LLVMHandleInfo(..) , LLVMContext(..) @@ -29,6 +31,9 @@ module Lang.Crucible.LLVM.Intrinsics.Common , symbolMap , mkLLVMContext -- ** register_llvm_override + , basic_llvm_override + , polymorphic1_llvm_override + , build_llvm_override , register_llvm_override , register_1arg_polymorphic_override @@ -50,6 +55,7 @@ import qualified Data.List as List import qualified Data.Text as Text import Numeric (readDec) +import qualified ABI.Itanium as ABI import qualified Data.Parameterized.Context as Ctx import Data.Parameterized.Some (Some(..)) import Data.Parameterized.TraversableFC (fmapFC) @@ -99,8 +105,20 @@ data SomeLLVMOverride p sym arch = llvmSizeT :: HasPtrWidth wptr => L.Type llvmSizeT = L.PrimType $ L.Integer $ fromIntegral $ natValue $ PtrWidth +data OverrideTemplate p sym arch rtp l a = + OverrideTemplate + { overrideTemplateMatcher :: TemplateMatcher + , overrideTemplateAction :: RegOverrideM p sym arch rtp l a () + } + +data TemplateMatcher + = ExactMatch String + | PrefixMatch String + | SubstringsMatch [String] + type RegOverrideM p sym arch rtp l a = - ReaderT L.Declare (MaybeT (StateT (LLVMContext arch) (OverrideSim p sym (LLVM arch) rtp l a))) + ReaderT (L.Declare, Maybe ABI.DecodedName) + (MaybeT (StateT (LLVMContext arch) (OverrideSim p sym (LLVM arch) rtp l a))) ------------------------------------------------------------------------ -- ** LLVMHandleInfo @@ -250,6 +268,13 @@ build_llvm_override sym fnm args ret args' ret' llvmOverride = do RegMap xs <- getOverrideArgs applyValTransformer fret =<< llvmOverride =<< applyArgTransformer fargs xs +polymorphic1_llvm_override :: forall p sym arch wptr l a rtp. + (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => + String -> + (forall w. (1 <= w) => NatRepr w -> SomeLLVMOverride p sym arch) -> + OverrideTemplate p sym arch rtp l a +polymorphic1_llvm_override prefix fn = + OverrideTemplate (PrefixMatch prefix) (register_1arg_polymorphic_override prefix fn) register_1arg_polymorphic_override :: forall p sym arch wptr l a rtp. (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => @@ -257,7 +282,7 @@ register_1arg_polymorphic_override :: forall p sym arch wptr l a rtp. (forall w. (1 <= w) => NatRepr w -> SomeLLVMOverride p sym arch) -> RegOverrideM p sym arch rtp l a () register_1arg_polymorphic_override prefix overrideFn = - do L.Symbol nm <- L.decName <$> ask + do L.Symbol nm <- L.decName . fst <$> ask case List.stripPrefix prefix nm of Just ('.':'i': (readDec -> (sz,[]):_)) | Some w <- mkNatRepr sz @@ -265,12 +290,19 @@ register_1arg_polymorphic_override prefix overrideFn = -> case overrideFn w of SomeLLVMOverride ovr -> register_llvm_override ovr _ -> empty +basic_llvm_override :: forall p args ret sym arch wptr l a rtp. + (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => + LLVMOverride p sym arch 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) + register_llvm_override :: forall p args ret sym arch wptr l a rtp. (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => LLVMOverride p sym arch args ret -> RegOverrideM p sym arch rtp l a () register_llvm_override llvmOverride = do - requestedDecl <- ask + requestedDecl <- fst <$> ask llvmctx <- get let decl = llvmOverride_declare llvmOverride diff --git a/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs b/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs index c8359a2d5..520009225 100644 --- a/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs +++ b/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs @@ -70,20 +70,27 @@ import Lang.Crucible.LLVM.Intrinsics.Common register_cpp_override :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => SomeCPPOverride p sym arch -> - RegOverrideM p sym arch rtp l a () -register_cpp_override someCPPOverride = do - requestedDecl <- ask - llvmctx <- get - case someCPPOverride requestedDecl llvmctx of - Just (SomeLLVMOverride override) -> - register_llvm_override override - Nothing -> empty + OverrideTemplate p sym arch rtp l a +register_cpp_override someCPPOverride = + OverrideTemplate (SubstringsMatch ("_Z" : cppOverrideSubstrings someCPPOverride)) $ + do (requestedDecl, decName) <- ask + llvmctx <- get + case decName of + Nothing -> empty + Just nm -> + case cppOverrideAction someCPPOverride requestedDecl nm llvmctx of + Nothing -> empty + Just (SomeLLVMOverride override) -> register_llvm_override override + -- type CPPOverride p sym arch args ret = -- L.Declare -> LLVMContext arch -> Maybe (LLVMOverride p sym arch args ret) -type SomeCPPOverride p sym arch = - L.Declare -> LLVMContext arch -> Maybe (SomeLLVMOverride p sym arch) +data SomeCPPOverride p sym arch = + SomeCPPOverride + { cppOverrideSubstrings :: [String] + , cppOverrideAction :: L.Declare -> ABI.DecodedName -> LLVMContext arch -> Maybe (SomeLLVMOverride p sym arch) + } ------------------------------------------------------------------------ -- ** No-ops @@ -91,12 +98,13 @@ type SomeCPPOverride p sym arch = ------------------------------------------------------------------------ -- *** Utilities -matchSymbolName :: (L.Symbol -> Bool) +matchSymbolName :: (L.Symbol -> ABI.DecodedName -> Bool) -> L.Declare + -> ABI.DecodedName -> Maybe a -> Maybe a -matchSymbolName match decl = - if not (match $ L.decName decl) +matchSymbolName match decl decodedName = + if not (match (L.decName decl) decodedName) then const Nothing else id @@ -118,26 +126,29 @@ panic_ from decl args ret = -- function handle in the symbol table and use that to construct an override mkOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => String -- ^ Name (for 'panic') + -> [String] -- ^ Substrings for name filtering -> (LLVMHandleInfo -> Maybe (SomeLLVMOverride p sym arch)) - -> (L.Symbol -> Bool) + -> (L.Symbol -> ABI.DecodedName -> Bool) -> SomeCPPOverride p sym arch -mkOverride name ov filt requestedDecl llvmctx = - matchSymbolName filt requestedDecl $ - case (Map.lookup (L.decName requestedDecl) (llvmctx ^. symbolMap)) of - Nothing -> panic name [ "No function handle for symbol:" - , show (L.decName requestedDecl) - ] - Just handleInfo -> ov handleInfo +mkOverride name substrings ov filt = + SomeCPPOverride substrings $ \requestedDecl decodedName llvmctx -> + matchSymbolName filt requestedDecl decodedName $ + case (Map.lookup (L.decName requestedDecl) (llvmctx ^. symbolMap)) of + Nothing -> panic name [ "No function handle for symbol:" + , show (L.decName requestedDecl) + ] + Just handleInfo -> ov handleInfo ------------------------------------------------------------------------ -- *** No-op override builders -- | Make an override for a function which doesn't return anything. voidOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) - => (L.Symbol -> Bool) + => [String] + -> (L.Symbol -> ABI.DecodedName -> Bool) -> SomeCPPOverride p sym arch -voidOverride = - mkOverride "voidOverride" $ \(LLVMHandleInfo decl handle) -> Just $ +voidOverride substrings = + mkOverride "voidOverride" substrings $ \(LLVMHandleInfo decl handle) -> Just $ case (handleArgTypes handle, handleReturnType handle) of (argTys, retTy@UnitRepr) -> SomeLLVMOverride $ LLVMOverride decl argTys retTy $ \_mem _sym _args -> @@ -149,10 +160,11 @@ voidOverride = -- -- The override simply returns its input. identityOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) - => (L.Symbol -> Bool) + => [String] + -> (L.Symbol -> ABI.DecodedName -> Bool) -> SomeCPPOverride p sym arch -identityOverride = - mkOverride "identityOverride" $ \(LLVMHandleInfo decl handle) -> Just $ +identityOverride substrings = + mkOverride "identityOverride" substrings $ \(LLVMHandleInfo decl handle) -> Just $ case (handleArgTypes handle, handleReturnType handle) of (argTys@(Ctx.Empty Ctx.:> argTy), retTy) | Just Refl <- testEquality argTy retTy -> @@ -166,10 +178,11 @@ identityOverride = -- -- The override simply returns its first input. constOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) - => (L.Symbol -> Bool) + => [String] + -> (L.Symbol -> ABI.DecodedName -> Bool) -> SomeCPPOverride p sym arch -constOverride = - mkOverride "constOverride" $ \(LLVMHandleInfo decl handle) -> Just $ +constOverride substrings = + mkOverride "constOverride" substrings $ \(LLVMHandleInfo decl handle) -> Just $ case (handleArgTypes handle, handleReturnType handle) of (argTys@(Ctx.Empty Ctx.:> fstTy Ctx.:> _), retTy) | Just Refl <- testEquality fstTy retTy -> @@ -182,10 +195,11 @@ constOverride = fixedOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => TypeRepr ty -> (GlobalVar Mem -> sym -> IO (RegValue sym ty)) - -> (L.Symbol -> Bool) + -> [String] + -> (L.Symbol -> ABI.DecodedName -> Bool) -> SomeCPPOverride p sym arch -fixedOverride ty regval = - mkOverride "fixedOverride" $ \(LLVMHandleInfo decl handle) -> Just $ +fixedOverride ty regval substrings = + mkOverride "fixedOverride" substrings $ \(LLVMHandleInfo decl handle) -> Just $ case (handleArgTypes handle, handleReturnType handle) of (argTys, retTy) | Just Refl <- testEquality retTy ty -> SomeLLVMOverride $ LLVMOverride decl argTys retTy $ \mem sym _args -> @@ -195,7 +209,8 @@ fixedOverride ty regval = -- | Return @true@. trueOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) - => (L.Symbol -> Bool) + => [String] + -> (L.Symbol -> ABI.DecodedName -> Bool) -> SomeCPPOverride p sym arch trueOverride = fixedOverride (LLVMPointerRepr knownNat) $ \_mem sym -> @@ -217,18 +232,18 @@ trueOverride = putToOverride12 :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => SomeCPPOverride p sym arch putToOverride12 = - constOverride $ \(L.Symbol nm) -> - case ABI.demangleName nm of - Right (ABI.Function - (ABI.NestedName - [] - [ ABI.SubstitutionPrefix ABI.SubStdNamespace - , _ - , ABI.UnqualifiedPrefix (ABI.SourceName "basic_ostream") - , ABI.TemplateArgsPrefix _ - ] - (ABI.OperatorName ABI.OpShl)) - [ABI.PointerToType (ABI.FunctionType _)]) -> True + constOverride ["St","ls","basic_ostream"] $ \_ decodedName -> + case decodedName of + ABI.Function + (ABI.NestedName + [] + [ ABI.SubstitutionPrefix ABI.SubStdNamespace + , _ + , ABI.UnqualifiedPrefix (ABI.SourceName "basic_ostream") + , ABI.TemplateArgsPrefix _ + ] + (ABI.OperatorName ABI.OpShl)) + [ABI.PointerToType (ABI.FunctionType _)] -> True _ -> False -- | Override for the \"put to\" operator, @<<@ @@ -238,7 +253,7 @@ putToOverride12 = putToOverride9 :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => SomeCPPOverride p sym arch putToOverride9 = - constOverride $ \(L.Symbol nm) -> + constOverride ["NSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc"] $ \(L.Symbol nm) _ -> nm == "_ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc" -- | TODO: When @itanium-abi@ get support for parsing templates, make this a @@ -246,7 +261,7 @@ putToOverride9 = endlOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => SomeCPPOverride p sym arch endlOverride = - identityOverride $ \(L.Symbol nm) -> + identityOverride ["endl","char_traits","basic_ostream"] $ \(L.Symbol nm) _decodedName -> and [ "endl" `isInfixOf` nm , "char_traits" `isInfixOf` nm , "basic_ostream" `isInfixOf` nm @@ -255,19 +270,19 @@ endlOverride = sentryOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => SomeCPPOverride p sym arch sentryOverride = - voidOverride $ \(L.Symbol nm) -> - case ABI.demangleName nm of - Right (ABI.Function - (ABI.NestedName - [] - [ ABI.SubstitutionPrefix ABI.SubStdNamespace - , _ - , ABI.UnqualifiedPrefix (ABI.SourceName "basic_ostream") - , _ - , ABI.UnqualifiedPrefix (ABI.SourceName "sentry") - ] - _) - _) -> True + voidOverride ["basic_ostream", "sentry"] $ \_nm decodedName -> + case decodedName of + ABI.Function + (ABI.NestedName + [] + [ ABI.SubstitutionPrefix ABI.SubStdNamespace + , _ + , ABI.UnqualifiedPrefix (ABI.SourceName "basic_ostream") + , _ + , ABI.UnqualifiedPrefix (ABI.SourceName "sentry") + ] + _) + _ -> True _ -> False -- | An override of the @bool@ operator (cast) on the @sentry@ class, @@ -276,18 +291,17 @@ sentryOverride = sentryBoolOverride :: (IsSymInterface sym, HasPtrWidth wptr, wptr ~ ArchWidth arch) => SomeCPPOverride p sym arch sentryBoolOverride = - trueOverride $ \(L.Symbol nm) -> - case ABI.demangleName nm of - Right (ABI.Function - (ABI.NestedName - [ABI.Const] - [ ABI.SubstitutionPrefix ABI.SubStdNamespace - , _ - , ABI.UnqualifiedPrefix (ABI.SourceName "basic_ostream") - , _ - , ABI.UnqualifiedPrefix (ABI.SourceName "sentry") - ] - (ABI.OperatorName (ABI.OpCast ABI.BoolType))) - [ABI.VoidType]) -> True + trueOverride ["basic_ostream", "sentry"] $ \_nm decodedName -> + case decodedName of + ABI.Function + (ABI.NestedName + [ABI.Const] + [ ABI.SubstitutionPrefix ABI.SubStdNamespace + , _ + , ABI.UnqualifiedPrefix (ABI.SourceName "basic_ostream") + , _ + , ABI.UnqualifiedPrefix (ABI.SourceName "sentry") + ] + (ABI.OperatorName (ABI.OpCast ABI.BoolType))) + [ABI.VoidType] -> True _ -> False - From 92942674cb6e3340afdff0e3ec69a177d5fcb519 Mon Sep 17 00:00:00 2001 From: robdockins Date: Fri, 10 May 2019 11:29:59 -0700 Subject: [PATCH 2/3] Update crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Common.hs Co-Authored-By: Langston Barrett --- crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Common.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Common.hs b/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Common.hs index 70e23715b..b2508b2ad 100644 --- a/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Common.hs +++ b/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Common.hs @@ -111,6 +111,8 @@ data OverrideTemplate p sym arch rtp l a = , overrideTemplateAction :: RegOverrideM p sym arch rtp l a () } +-- | This type controls whether an override is installed for a given name found in a module. +-- See 'filterTemplates'. data TemplateMatcher = ExactMatch String | PrefixMatch String From b28dc1e1abae9d0e650b1a74d4e0635997785e0e Mon Sep 17 00:00:00 2001 From: robdockins Date: Fri, 10 May 2019 11:30:20 -0700 Subject: [PATCH 3/3] Update crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs Co-Authored-By: Langston Barrett --- crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs b/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs index 520009225..518946ece 100644 --- a/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs +++ b/crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs @@ -86,6 +86,9 @@ register_cpp_override someCPPOverride = -- type CPPOverride p sym arch args ret = -- L.Declare -> LLVMContext arch -> Maybe (LLVMOverride p sym arch args ret) +-- | We can only tell whether we should install a C++ override after demangling +-- the function name, which is expensive. As a first approximation, we ask whether +-- the function's name contains a few substrings, in order. data SomeCPPOverride p sym arch = SomeCPPOverride { cppOverrideSubstrings :: [String]