packages feed

hLLVM-0.5.0.0: src/Llvm/Pass/Uda.hs

{-# OPTIONS_GHC -cpp #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}

#define FLC   (FileLoc $(srcLoc))
{-
  This module compute the use, def, and Addr of CoreIr
-}
module Llvm.Pass.Uda where
import Llvm.Data.CoreIr
import qualified Data.Set as Ds
import Data.Monoid
import Prelude (Show, Eq, Ord, fst, (.), ($), map, maybe, Maybe, (++), show, Bool(False), undefined, foldl,error
               ,fmap)
#ifdef DEBUG
import Debug.Trace
#endif

import Llvm.Query.TypeConstValue
import Llvm.Query.IrCxt
import qualified Llvm.Query.TypeConstValue as Tc

class Uda a where
  use :: a -> Ds.Set GlobalOrLocalId
  def :: a -> Ds.Set LocalId -- defined ssa variables
  
  storeTo :: a -> Ds.Set Value
  storeTo _ = Ds.empty
  
  loadFrom :: a -> Ds.Set Value
  loadFrom _ = Ds.empty 
  
instance Uda Const where
  use c = case c of
    C_globalAddr i -> Ds.insert (GolG i) Ds.empty
    _ -> Ds.empty
  def _ = Ds.empty

instance Uda v => Uda (GetElementPtr s v) where
  use (GetElementPtr _ (T _ ptr) indices) = use ptr `Ds.union` (foldl (\p e -> Ds.union p (use e)) Ds.empty indices)
  def _ = Ds.empty
  
instance Uda v => Uda (Maybe v) where  
  use x = maybe Ds.empty use x
  def x = maybe Ds.empty def x
  storeTo x = maybe Ds.empty storeTo x
  
instance Uda v => Uda (T t v) where  
  use (T _ x) = use x
  def (T _ x) = def x
  storeTo (T _ x) = storeTo x
  
instance Uda LocalId where
  use x = Ds.insert (GolL x) Ds.empty
  def x = Ds.insert x Ds.empty
  storeTo x = Ds.insert (Val_ssa x) Ds.empty
  
instance Uda Value where
  use x = case x of
    Val_ssa l -> Ds.insert (GolL l) Ds.empty
    Val_const c -> use c
  def _ = error $ "cannot happen"
  storeTo x = Ds.insert x Ds.empty
 
instance Uda ActualParam where
  use ap = case ap of
    ActualParamData _ _ _ v _ -> use v
    ActualParamLabel _ _ _ v _ -> use v
    ActualParamMeta _ -> Ds.empty
  def _ = errorLoc FLC $ "cannot happen"
  storeTo _ = errorLoc FLC $ "cannot happen"
  loadFrom _ = errorLoc FLC $ "cannot happen"
  
  
instance Uda x => Uda [x] where  
  use l = Ds.unions (fmap use l)
  def l = Ds.unions (fmap def l)
  storeTo l = Ds.unions (fmap storeTo l)
  loadFrom l = Ds.unions (fmap loadFrom l)

instance Uda CallSite where
  use x = case x of
    CsFun _ _ _ _ l _ -> use l
    CsAsm _ _ _ _ _ _ l _ -> use l
    CsConversion _ _ _ l _ -> use l

instance Uda CInst where 
  use ci = case ci of
    I_alloca{..} -> use size
    I_load{..} -> use pointer
    I_loadatomic{..} -> use pointer
    I_store{..} -> Ds.union (use storedvalue) (use pointer)
    I_storeatomic{..} -> Ds.union (use storedvalue) (use pointer)
    I_fence{..} -> Ds.empty
    I_cmpxchg_I{..} -> Ds.unions [use pointer,use cmpi,use newi]
    I_cmpxchg_F{..} -> Ds.unions [use pointer,use cmpf,use newf]
    I_cmpxchg_P{..} -> Ds.unions [use pointer,use cmpp,use newp]
    I_atomicrmw{..} -> Ds.unions [use pointer,use val]
    I_call_fun{..} -> use actualParams
    I_call_other{..} -> use callSite
    I_extractelement_I{..} -> Ds.unions [use vectorI, use index]
    I_extractelement_F{..} -> Ds.unions [use vectorF, use index]
    I_extractelement_P{..} -> Ds.unions [use vectorP, use index]
    I_bitcast{..} -> use srcP
    I_ptrtoint{..} -> use srcP
    I_inttoptr{..} -> use srcI
    I_add{..} -> use operand1 `mappend` use operand2
    I_getelementptr{..} -> use pointer `mappend` (foldl (\p e -> p `mappend` (use e)) Ds.empty indices)
    I_getelementptr_V{..} -> use vpointer `mappend` (foldl (\p e -> p `mappend` (use e)) Ds.empty vindices)
    I_llvm_dbg_declare{..} -> Ds.empty
    I_icmp{..} -> use operand1 `mappend` use operand2
    I_icmp_V{..} -> use operand1 `mappend` use operand2
    I_va_end{..} -> use pointer
    I_va_start{..} -> use pointer
    I_va_arg tv _ _ -> use tv
    _ -> errorLoc FLC $ "unsupported " ++ show ci
  def ci = case ci of
    I_alloca{..} -> def result
    I_load{..} -> def result
    I_store{..} -> Ds.empty
    I_bitcast{..} -> def result
    I_ptrtoint{..} -> def result
    I_inttoptr{..} -> def result
    I_add{..} -> def result
    I_sub{..} -> def result
    I_mul{..} -> def result
    I_udiv{..} -> def result
    I_sdiv{..} -> def result
    I_urem{..} -> def result
    I_srem{..} -> def result
    I_shl{..} -> def result
    I_lshr{..} -> def result
    I_ashr{..} -> def result    
    I_and{..} -> def result    
    I_or{..} -> def result        
    I_xor{..} -> def result 
    I_getelementptr{..} -> def result
    I_llvm_dbg_declare{..} -> Ds.empty
    I_icmp{..} -> def result
    I_icmp_V{..} -> def result
    I_trunc{..} -> def result
    I_sext{..} -> def result
    I_va_start{..} -> Ds.empty
    I_va_arg{..} -> def result
    I_va_end{..} -> Ds.empty
    _ -> errorLoc FLC $ "unsupported " ++ show ci    
  storeTo ci = case ci of
    I_store{..} -> storeTo pointer
    I_va_start tv -> storeTo tv
    _ -> Ds.empty
  loadFrom ci = case ci of
    I_load{..} -> let T _ v = pointer
                  in Ds.insert v Ds.empty
    _ -> Ds.empty


instance Uda CInstWithDbg where  
  use (CInstWithDbg ci _) = use ci
  def (CInstWithDbg ci _) = def ci
  storeTo (CInstWithDbg ci _) = storeTo ci
  loadFrom (CInstWithDbg ci _) = loadFrom ci