-- Copyright (C) 2018-2024 Jun Zhang <zhangjunphy[at]gmail[dot]com>
--
-- This file is a part of decafc.
--
-- decafc is free software: you can redistribute it and/or modify it under the
-- terms of the MIT (X11) License as described in the LICENSE file.
--
-- decafc is distributed in the hope that it will be useful, but WITHOUT ANY
-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE.  See the X11 license for more details.

module CFG.Types where

import Data.Generics.Labels
import GHC.Generics (Generic)
import SSA
import Types
import Util.Graph qualified as G
import Data.Map (Map)
import qualified AST

data Condition
  = Pred {Condition -> VarOrImm
pred :: !VarOrImm}
  | Complement {pred :: !VarOrImm}
  deriving (Int -> Condition -> ShowS
[Condition] -> ShowS
Condition -> String
(Int -> Condition -> ShowS)
-> (Condition -> String)
-> ([Condition] -> ShowS)
-> Show Condition
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Condition -> ShowS
showsPrec :: Int -> Condition -> ShowS
$cshow :: Condition -> String
show :: Condition -> String
$cshowList :: [Condition] -> ShowS
showList :: [Condition] -> ShowS
Show)

data BasicBlock = BasicBlock
  { BasicBlock -> Int
bbid :: !BBID,
    BasicBlock -> Int
sid :: !ScopeID,
    BasicBlock -> [SSA]
statements :: ![SSA]
  }
  deriving ((forall x. BasicBlock -> Rep BasicBlock x)
-> (forall x. Rep BasicBlock x -> BasicBlock) -> Generic BasicBlock
forall x. Rep BasicBlock x -> BasicBlock
forall x. BasicBlock -> Rep BasicBlock x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. BasicBlock -> Rep BasicBlock x
from :: forall x. BasicBlock -> Rep BasicBlock x
$cto :: forall x. Rep BasicBlock x -> BasicBlock
to :: forall x. Rep BasicBlock x -> BasicBlock
Generic, Int -> BasicBlock -> ShowS
[BasicBlock] -> ShowS
BasicBlock -> String
(Int -> BasicBlock -> ShowS)
-> (BasicBlock -> String)
-> ([BasicBlock] -> ShowS)
-> Show BasicBlock
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BasicBlock -> ShowS
showsPrec :: Int -> BasicBlock -> ShowS
$cshow :: BasicBlock -> String
show :: BasicBlock -> String
$cshowList :: [BasicBlock] -> ShowS
showList :: [BasicBlock] -> ShowS
Show)

data CFGEdge
  = SeqEdge
  | CondEdge !Condition
  deriving (Int -> CFGEdge -> ShowS
[CFGEdge] -> ShowS
CFGEdge -> String
(Int -> CFGEdge -> ShowS)
-> (CFGEdge -> String) -> ([CFGEdge] -> ShowS) -> Show CFGEdge
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CFGEdge -> ShowS
showsPrec :: Int -> CFGEdge -> ShowS
$cshow :: CFGEdge -> String
show :: CFGEdge -> String
$cshowList :: [CFGEdge] -> ShowS
showList :: [CFGEdge] -> ShowS
Show)

-- type CFG = G.Graph BBID CFGNode CFGEdge

data CFG = CFG
  { CFG -> Graph Int BasicBlock CFGEdge
graph :: !(G.Graph BBID BasicBlock CFGEdge),
    CFG -> Int
entry :: !BBID,
    CFG -> Int
exit :: !BBID,
    CFG -> [Var]
arguments :: ![Var],
    CFG -> MethodSig
sig :: !AST.MethodSig
  }
  deriving ((forall x. CFG -> Rep CFG x)
-> (forall x. Rep CFG x -> CFG) -> Generic CFG
forall x. Rep CFG x -> CFG
forall x. CFG -> Rep CFG x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. CFG -> Rep CFG x
from :: forall x. CFG -> Rep CFG x
$cto :: forall x. Rep CFG x -> CFG
to :: forall x. Rep CFG x -> CFG
Generic)

type CFGBuilder = G.GraphBuilder BBID BasicBlock CFGEdge

data SingleFileCFG = SingleFileCFG
  { SingleFileCFG -> [Name]
declares :: ![Name],          -- Foreign functions
    SingleFileCFG -> [(Var, Type)]
global :: ![(Var, AST.Type)], -- Global variables
    SingleFileCFG -> Map Name CFG
cfgs :: !(Map Name CFG)
  } deriving ((forall x. SingleFileCFG -> Rep SingleFileCFG x)
-> (forall x. Rep SingleFileCFG x -> SingleFileCFG)
-> Generic SingleFileCFG
forall x. Rep SingleFileCFG x -> SingleFileCFG
forall x. SingleFileCFG -> Rep SingleFileCFG x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. SingleFileCFG -> Rep SingleFileCFG x
from :: forall x. SingleFileCFG -> Rep SingleFileCFG x
$cto :: forall x. Rep SingleFileCFG x -> SingleFileCFG
to :: forall x. Rep SingleFileCFG x -> SingleFileCFG
Generic)