diff options
author | tomsmeding <tom.smeding@gmail.com> | 2017-08-19 11:05:43 +0200 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2017-08-19 11:05:43 +0200 |
commit | 694ec05bcad01fd27606aace73b49cdade16945e (patch) | |
tree | 5c7a0433232f0860ef18f1634510d4f823ce5bdb /Intermediate.hs |
Initial
Diffstat (limited to 'Intermediate.hs')
-rw-r--r-- | Intermediate.hs | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/Intermediate.hs b/Intermediate.hs new file mode 100644 index 0000000..5f3a9f2 --- /dev/null +++ b/Intermediate.hs @@ -0,0 +1,174 @@ +module Intermediate where + +import Data.Bits +import Data.List + +import AST +import Defs +import Pretty + + +data BB = BB Id [IRIns] IRTerm + deriving (Show, Eq) + +data Ref = Temp Size Int | Argument Size Name | Global Size Name | Constant Size Value + deriving (Show, Eq, Ord) + +data IRProgram = IRProgram [DVar] [IRFunc] + deriving (Show, Eq) + +data IRFunc = IRFunc (Maybe Type) Name [(Type, Name)] [BB] Id + deriving (Show, Eq) + +data IRIns + = IMov Ref Ref + | IStore Ref Ref + | ILoad Ref Ref + | IAri ArithType Ref Ref + | ICall Name [Ref] + | ICallr Ref Name [Ref] + | IResize Ref Ref + | INop + deriving (Show, Eq) + +data IRTerm + = IJcc CmpType Ref Ref Id Id -- Id Id == if-yes if-no + | IJmp Id + | IRet + | IRetr Ref + | ITermNone + deriving (Show, Eq) + +data ArithType + = AAdd | ASub | AMul | ADiv | AMod + | AAnd | AOr | AXor + | AEq | ANeq | AGt | ALt | AGeq | ALeq + deriving (Show, Eq) + +data CmpType + = CEq | CNeq | CGt | CLt | CGeq | CLeq + deriving (Show, Eq) + + +refSize :: Ref -> Size +refSize (Temp sz _) = sz +refSize (Argument sz _) = sz +refSize (Global sz _) = sz +refSize (Constant sz _) = sz + + +instance Pretty BB where + prettyI i (BB bid inss term) = + "{{{(" ++ show bid ++ ")\n" ++ indent (i+1) ++ + intercalate ("\n" ++ indent (i+1)) (map pretty inss) ++ + (if null inss then "" else "\n" ++ indent (i+1)) ++ + pretty term ++ + "\n" ++ indent i ++ "}}}" + where + indent n = replicate (2*n) ' ' + +instance Pretty Ref where + prettyI _ (Temp sz k) = "t" ++ show k ++ pretty_sizeSuffix sz + prettyI _ (Argument sz n) = "a" ++ n ++ pretty_sizeSuffix sz + prettyI _ (Global sz n) = "g" ++ n ++ pretty_sizeSuffix sz + prettyI _ (Constant sz n) = show n ++ pretty_sizeSuffix sz + +pretty_sizeSuffix :: Size -> String +pretty_sizeSuffix 1 = "B" +pretty_sizeSuffix 2 = "W" +pretty_sizeSuffix 4 = "D" +pretty_sizeSuffix 8 = "Q" +pretty_sizeSuffix sz = "<" ++ show sz ++ ">" + +instance Pretty IRProgram where + prettyI i (IRProgram vars funcs) = + intercalate ("\n" ++ indent i) (map (prettyI i) vars) ++ + "\n" ++ indent i ++ + intercalate ("\n" ++ indent i) (map (prettyI (i+1)) funcs) ++ + "\n" + where + indent n = replicate (2*n) ' ' + +instance Pretty IRFunc where + prettyI i (IRFunc mt n al bbs sid) = + "irfunc" ++ maybe "" ((' ' :) . prettyI i) mt ++ " " ++ n ++ "(" ++ + intercalate "," + (map (\(at,an) -> prettyI i at ++ " " ++ an) al) ++ + ")\n" ++ indent i ++ + intercalate ("\n" ++ indent i) (map (prettyI i) sorted) + where + indent n' = replicate (2*n') ' ' + + sorted = uncurry (++) $ partition (\(BB bid _ _) -> bid == sid) bbs + +instance Pretty IRIns where + prettyI _ (IMov d s) = "mov " ++ pretty d ++ " <- " ++ pretty s + prettyI _ (IStore d s) = "store *" ++ pretty d ++ " <- " ++ pretty s + prettyI _ (ILoad d s) = "load " ++ pretty d ++ " <- *" ++ pretty s + prettyI _ (IAri at d s) = + pretty at ++ " " ++ pretty d ++ ", " ++ pretty s + prettyI _ (ICall n al) = + "call " ++ n ++ " (" ++ intercalate ", " (map pretty al) ++ ")" + prettyI _ (ICallr d n al) = + "call " ++ pretty d ++ " <- " ++ n ++ " (" ++ intercalate ", " (map pretty al) ++ ")" + prettyI _ (IResize d s) = "resize " ++ pretty d ++ " <- " ++ pretty s + prettyI _ INop = "nop" + +instance Pretty IRTerm where + prettyI _ (IJcc ct s1 s2 did1 did2) = + pretty ct ++ " " ++ pretty s1 ++ ", " ++ pretty s2 ++ " -> " ++ show did1 ++ " | " ++ show did2 + prettyI _ (IJmp did) = "jmp " ++ show did + prettyI _ IRet = "ret" + prettyI _ (IRetr ref) = "retr " ++ pretty ref + prettyI _ ITermNone = "?NONE?" + +instance Pretty ArithType where + prettyI _ AAdd = "add" + prettyI _ ASub = "sub" + prettyI _ AMul = "mul" + prettyI _ ADiv = "div" + prettyI _ AMod = "mod" + prettyI _ AAnd = "and" + prettyI _ AOr = "or" + prettyI _ AXor = "xor" + prettyI _ AEq = "eq" + prettyI _ ANeq = "neq" + prettyI _ AGt = "gt" + prettyI _ ALt = "lt" + prettyI _ AGeq = "geq" + prettyI _ ALeq = "leq" + +instance Pretty CmpType where + prettyI _ CEq = "jeq" + prettyI _ CNeq = "jne" + prettyI _ CGt = "jg" + prettyI _ CLt = "jl" + prettyI _ CGeq = "jge" + prettyI _ CLeq = "jle" + + +evaluateArith :: ArithType -> Value -> Value -> Value +evaluateArith at a b = case at of + AAdd -> a + b + ASub -> a - b + AMul -> a * b + ADiv -> if b == 0 then error "Division by zero detected" else a `div` b + AMod -> if b == 0 then error "Modulo by zero detected" else a `mod` b + AAnd -> a .&. b + AOr -> a .|. b + AXor -> a `xor` b + AEq -> if a == b then 1 else 0 + ANeq -> if a /= b then 1 else 0 + AGt -> if a > b then 1 else 0 + ALt -> if a < b then 1 else 0 + AGeq -> if a >= b then 1 else 0 + ALeq -> if a <= b then 1 else 0 + +evaluateCmp :: CmpType -> Value -> Value -> Bool +evaluateCmp ct a b = case ct of + CEq -> a == b + CNeq -> a /= b + CGt -> a > b + CLt -> a < b + CGeq -> a >= b + CLeq -> a <= b |