@@ -23,6 +23,7 @@ import qualified Data.BitCode.LLVM.Codes.Function as FC
2323import qualified Data.BitCode.LLVM.Codes.ValueSymtab as VST
2424import qualified Data.Map.Strict as Map
2525import Data.Map.Strict (Map )
26+ import qualified Data.Set as Set
2627
2728import Data.BitCode.LLVM.Classes.ToSymbols
2829import Data.List (elemIndex , sort , sortBy , groupBy , nub )
@@ -42,7 +43,7 @@ import Data.BitCode (denormalize)
4243import Data.BitCode.Writer (emitTopLevel )
4344import Data.BitCode.Writer.Monad (evalBitCodeWriter , ask )
4445
45- import Data.BitCode.LLVM.Pretty
46+ import Data.BitCode.LLVM.Pretty hiding ( prettyIndexed )
4647import Data.BitCode.LLVM.Util
4748import Text.PrettyPrint ((<+>) , text , (<>) , int , vcat , Doc , ($+$) , empty )
4849import Control.Applicative ((<|>) )
@@ -68,28 +69,47 @@ instance (ToNBitCode a) => ToNBitCode [a] where
6869
6970instance {-# OVERLAPPING #-} ToNBitCode [T. Ty ] where
7071 toBitCode tys
71- = pure $ mkBlock TYPE_NEW (numEntryRec: concatMap mkTypeRec tys)
72- where numEntryRec :: NBitCode
72+ = pure $ mkBlock TYPE_NEW (numEntryRec: concatMap mkTypeRec (zip [0 .. ] tys))
73+ where -- A "safe" type lookup, that ensure we do not forward reference, which
74+ -- is only permissable for named structs.
75+ typeList = vcat (map p (zip [(0 :: Int ).. ] tys))
76+ where p (i, t) = pretty i <+> text " : " <+> pretty t <+> text (show t)
77+ lookupTypeIndex' :: (HasCallStack , Integral b ) => Int -> T. Ty -> Maybe b
78+ lookupTypeIndex' n t = let t' = lookupTypeIndex tys t
79+ in if (fromIntegral t') < n then Just t' else Nothing
80+ numEntryRec :: NBitCode
7381 numEntryRec = mkRec TC. NUMENTRY (length tys)
74- mkTypeRec :: T. Ty -> [NBitCode ]
75- mkTypeRec T. Void = [ mkEmptyRec TC. VOID ]
76- mkTypeRec T. Float = [ mkEmptyRec TC. FLOAT ]
77- mkTypeRec T. Double = [ mkEmptyRec TC. DOUBLE ]
78- mkTypeRec T. Label = [ mkEmptyRec TC. LABEL ]
79- mkTypeRec (T. Opaque name) = [ mkRec TC. STRUCT_NAME name, mkEmptyRec TC. OPAQUE ]
80- mkTypeRec (T. Int w) = [ mkRec TC. INTEGER [w] ]
81- mkTypeRec (T. Ptr s t) = [ mkRec TC. POINTER [lookupTypeIndex tys t, s] ]
82- mkTypeRec T. Half = [ mkEmptyRec TC. HALF ]
83- mkTypeRec (T. Array n t) = [ mkRec TC. ARRAY [n, lookupTypeIndex tys t] ]
84- mkTypeRec (T. Vector n t) = [ mkRec TC. VECTOR [n, lookupTypeIndex tys t] ]
85- mkTypeRec T. X86Fp80 = [ mkEmptyRec TC. X86_FP80 ]
86- mkTypeRec T. Fp128 = [ mkEmptyRec TC. FP128 ]
87- mkTypeRec T. Metadata = [ mkEmptyRec TC. METADATA ]
88- mkTypeRec T. X86Mmx = [ mkEmptyRec TC. X86_MMX ]
89- mkTypeRec (T. StructAnon p ts) = [ mkRec TC. STRUCT_ANON ((if p then 1 else 0 :: Int ): map (lookupTypeIndex tys) ts) ]
90- mkTypeRec (T. StructNamed name p ts)= [ mkRec TC. STRUCT_NAME name, mkRec TC. STRUCT_NAMED ((if p then 1 else 0 :: Int ): map (lookupTypeIndex tys) ts) ]
91- mkTypeRec (T. Function vargs t ts) = [ mkRec TC. FUNCTION ((if vargs then 1 else 0 :: Int ): map (lookupTypeIndex tys) (t: ts)) ]
92- mkTypeRec T. Token = [ mkEmptyRec TC. TOKEN ]
82+ mkTypeRec :: (Int , T. Ty ) -> [NBitCode ]
83+ mkTypeRec (i, T. Void ) = [ mkEmptyRec TC. VOID ]
84+ mkTypeRec (i, T. Float ) = [ mkEmptyRec TC. FLOAT ]
85+ mkTypeRec (i, T. Double ) = [ mkEmptyRec TC. DOUBLE ]
86+ mkTypeRec (i, T. Label ) = [ mkEmptyRec TC. LABEL ]
87+ mkTypeRec (i, (T. Opaque name)) = [ mkRec TC. STRUCT_NAME name, mkEmptyRec TC. OPAQUE ]
88+ mkTypeRec (i, (T. Int w)) = [ mkRec TC. INTEGER [w] ]
89+ mkTypeRec (i, ty@ (T. Ptr s t))
90+ | Just t' <- lookupTypeIndex' i t = [ mkRec TC. POINTER [t', s] ]
91+ | otherwise = error $ " Pointee " ++ show t ++ " must be emitted before " ++ show ty
92+ mkTypeRec (i, T. Half ) = [ mkEmptyRec TC. HALF ]
93+ mkTypeRec (i, ty@ (T. Array n t))
94+ | Just t' <- lookupTypeIndex' i t = [ mkRec TC. ARRAY [n, t'] ]
95+ | otherwise = error $ " Array " ++ show ty ++ " must not forward reference " ++ show t
96+ mkTypeRec (i, ty@ (T. Vector n t))
97+ | Just t' <- lookupTypeIndex' i t = [ mkRec TC. VECTOR [n, t'] ]
98+ | otherwise = error $ " Vector " ++ show ty ++ " must not forward reference " ++ show t
99+ mkTypeRec (i, T. X86Fp80 ) = [ mkEmptyRec TC. X86_FP80 ]
100+ mkTypeRec (i, T. Fp128 ) = [ mkEmptyRec TC. FP128 ]
101+ mkTypeRec (i, T. Metadata ) = [ mkEmptyRec TC. METADATA ]
102+ mkTypeRec (i, T. X86Mmx ) = [ mkEmptyRec TC. X86_MMX ]
103+ mkTypeRec (i, ty@ (T. StructAnon p ts))
104+ | Just ts' <- mapM (lookupTypeIndex' i) ts = [ mkRec TC. STRUCT_ANON ((if p then 1 else 0 :: Int ): ts') ]
105+ | otherwise = error $ " Anon Struct " ++ show (pretty ty) ++ " must not forward reference its types " ++ show (pretty ts)
106+ mkTypeRec (i, (T. StructNamed name p ts))= [ mkRec TC. STRUCT_NAME name, mkRec TC. STRUCT_NAMED ((if p then 1 else 0 :: Int ): map (lookupTypeIndex tys) ts) ]
107+ 108+ mkTypeRec (i, ty@ (T. Function vargs t ts))
109+ | Just ts' <- mapM (lookupTypeIndex' i) (t: ts) = [ mkRec TC. FUNCTION ((if vargs then 1 else 0 :: Int ): ts') ]
110+ | otherwise = error . show $ text " Function" <+> pretty ty <+> text " must not forward reference its types" <+> pretty (t: ts)
111+ $+$ text " Types:" $+$ typeList
112+ mkTypeRec (i, T. Token ) = [ mkEmptyRec TC. TOKEN ]
93113
94114
95115lookupIndexGeneric :: (HasCallStack , Pretty a , Eq a , Show a , Integral b ) => [a ] -> a -> b
@@ -229,15 +249,20 @@ instance ToNBitCode (Maybe Ident, Module) where
229249
230250 -- * T Y P E S
231251 -- all top level types, and all the types to construct them. (e.g. i8** -> i8, i8*, and i8**).
232- topLevelTypes = foldl T. ftypes [] $ map ty flatSymbols
252+ -- topLevelTypes = foldl T.ftypes [] $ map ty flatSymbols
233253 -- all symbols of functions, their constants and bodies.
234- fullFunctionSymbols = fsymbols [] mFns
254+ -- fullFunctionSymbols = fsymbols [] mFns
235255 -- The type list now additionally also contains all types that are
236256 -- part of the function signatures, bodies and constants.
237257 --
238258 -- TODO: FLAGS: if -dump-typelist:
239- -- traceShowWith prettyIndexed $!
240- typeList = foldl T. ftypes topLevelTypes $ map ty fullFunctionSymbols
259+ -- traceShowWith prettyIndexed $!
260+ -- typeListO = foldl T.ftypes topLevelTypes $ map ty fullFunctionSymbols
261+ -- typeList = traceShowWith (\x -> text "ORIGINAL:"
262+ -- $+$ prettyIndexed typeListO
263+ -- $+$ text "OPTIMIZED:"
264+ -- $+$ prettyIndexed x ) $!
265+ typeList = sortBy T. typeCompare (Set. toList mTypes) --
241266
242267 -- | Turn a set of Constant Values unto BitCode Records.
243268 mkConstBlock :: HasCallStack
0 commit comments