diff --git a/Stage6/CodeGen.hs b/Stage6/CodeGen.hs index 0c25935..9b479de 100644 --- a/Stage6/CodeGen.hs +++ b/Stage6/CodeGen.hs @@ -7,7 +7,6 @@ import qualified Data.Map as Map import LabelLink (replaceLabels) import SymbolTable import SyntaxTree -import TypeTable import XsmGen allRegs :: [String] @@ -26,42 +25,38 @@ getRegsUsed freeRegs = allRegs \\ freeRegs -- | resolves a symbol name and returns the address in a register -- | symName -> reg -> globalSymbolT -> localSymbolT -> (code, sym) -symbolResolve :: String -> String -> GSymbolTable -> LSymbolTable -> (String, String) +symbolResolve :: String -> String -> GSymbolTable -> LSymbolTable -> String symbolResolve name r gst lst = case Map.lookup name lst of - Just (lType, lAddr) -> (lType, genMovXsm r "BP" ++ genArmcXsm '+' r (show lAddr)) - Nothing -> let sym = gst Map.! name in (getSymbolType sym, genMovXsm r (show $ getSymbolAddress sym)) + Just (lType, lAddr) -> genMovXsm r "BP" ++ genArmcXsm '+' r (show lAddr) + Nothing -> let sym = gst Map.! name in genMovXsm r (show $ getSymbolAddress sym) -- | Resolves a dot field and returns code. Stores final address in passed register --- | tTable -> startType -> reg(with sym address) -> dotlist -> tempReg -> Code -dotResolve :: TypeTable -> String -> String -> [String] -> String -> String -dotResolve _ _ _ [] _ = "" -dotResolve tTable p r (c : ds) tempReg = code ++ dotResolve tTable cType r ds tempReg +-- | dotlist -> reg(with sym address) -> tempReg -> Code +dotResolve :: [Int] -> String -> String -> String +dotResolve [] _ _ = "" +dotResolve (c : ds) r tempReg = code ++ dotResolve ds r tempReg where - pFields = tTable Map.! p - (childIndex, (cType, _)) = case findIndex ((c ==) . snd) pFields of - Just i -> (i, pFields !! i) - Nothing -> error "Shouldn't be an error" - code = genMovXsm tempReg (accessMem r) ++ genArmcXsm '+' tempReg (show childIndex) ++ genMovXsm r tempReg + code = genMovXsm tempReg (accessMem r) ++ genArmcXsm '+' tempReg (show c) ++ genMovXsm r tempReg -- | varName -> resolver -> freeRegs -> GSymbolTable -> LSymbolTable -> (code, reg, remainingRegs) -- | Returns code to resolve a variable address and stores the address in a register -genAddrResolveCode :: String -> VarResolve -> [String] -> GSymbolTable -> LSymbolTable -> TypeTable -> (String, String, [String]) -genAddrResolveCode name Simple regs gst lst _ = (symCode, symReg, regs2) +genAddrResolveCode :: String -> VarResolve -> [String] -> GSymbolTable -> LSymbolTable -> (String, String, [String]) +genAddrResolveCode name Simple regs gst lst = (symCode, symReg, regs2) where (symReg, regs2) = getReg regs - (_, symCode) = symbolResolve name symReg gst lst -genAddrResolveCode name Deref regs gst lst _ = (symCode ++ genMovXsm valReg (accessMem symReg), valReg, regs2) + symCode = symbolResolve name symReg gst lst +genAddrResolveCode name Deref regs gst lst = (symCode ++ genMovXsm valReg (accessMem symReg), valReg, regs2) where (valReg, regs2) = getReg regs (symReg, regs3) = getReg regs2 - (_, symCode) = symbolResolve name symReg gst lst -genAddrResolveCode name (Dot dotList) regs gst lst tTable = (symCode ++ dotCode, valReg, regs2) + symCode = symbolResolve name symReg gst lst +genAddrResolveCode name (Dot dotList) regs gst lst = (symCode ++ dotCode, valReg, regs2) where (valReg, regs2) = getReg regs (tempReg, _) = getReg regs2 - (symType, symCode) = symbolResolve name valReg gst lst - dotCode = dotResolve tTable symType valReg dotList tempReg -genAddrResolveCode name (Index i) regs gst lst _ = + symCode = symbolResolve name valReg gst lst + dotCode = dotResolve dotList valReg tempReg +genAddrResolveCode name (Index i) regs gst lst = ( symCode ++ iCode ++ genArmcXsm '+' symReg iReg, @@ -71,8 +66,8 @@ genAddrResolveCode name (Index i) regs gst lst _ = where (symReg, regs2) = getReg regs (iCode, iReg, _, _) = genCode Args {node = i, regsFree = regs2, gSymTable = gst, lSymTable = lst} - (_, symCode) = symbolResolve name symReg gst lst -genAddrResolveCode name (Index2D i j) regs gst lst _ = + symCode = symbolResolve name symReg gst lst +genAddrResolveCode name (Index2D i j) regs gst lst = ( symCode ++ iCode ++ jCode @@ -85,17 +80,17 @@ genAddrResolveCode name (Index2D i j) regs gst lst _ = where (symReg, regs2) = getReg regs (iCode, iReg, regs3, _) = genCode Args {node = i, regsFree = regs2, gSymTable = gst, lSymTable = lst, labels = [], blockLabels = Nothing} - (_, symCode) = symbolResolve name symReg gst lst + symCode = symbolResolve name symReg gst lst (Arr2 _ m n _) = gst Map.! name (jCode, jReg, _, _) = genCode Args {node = j, regsFree = regs3, gSymTable = gst, lSymTable = lst, labels = [], blockLabels = Nothing} --- | varName -> resolver -> freeRegs -> GSymbolTable -> LSymbolTable -> TypeTable -> (code, reg, remainingRegs) +-- | varName -> resolver -> freeRegs -> GSymbolTable -> LSymbolTable -> (code, reg, remainingRegs) -- | Returns code to resolve a variable value and stores the value in a register -genValResolveCode :: String -> VarResolve -> [String] -> GSymbolTable -> LSymbolTable -> TypeTable -> (String, String, [String]) -genValResolveCode name resolv regs gst lst tt = (addrCode ++ genMovXsm valReg (accessMem addrReg), valReg, rs) +genValResolveCode :: String -> VarResolve -> [String] -> GSymbolTable -> LSymbolTable -> (String, String, [String]) +genValResolveCode name resolv regs gst lst = (addrCode ++ genMovXsm valReg (accessMem addrReg), valReg, rs) where (valReg, rs) = getReg regs - (addrCode, addrReg, _) = genAddrResolveCode name resolv rs gst lst tt + (addrCode, addrReg, _) = genAddrResolveCode name resolv rs gst lst data CodeArgs = Args { node :: SyntaxTree, @@ -103,8 +98,7 @@ data CodeArgs = Args labels :: [String], blockLabels :: Maybe (String, String), gSymTable :: GSymbolTable, - lSymTable :: LSymbolTable, - tTable :: TypeTable + lSymTable :: LSymbolTable } -- | syntaxTree -> freeRegisters -> labels -> Maybe (startLabel, endLabel) -> (code, usedregister, remainingRegisters, remainingLabels) @@ -125,8 +119,8 @@ genCode a@Args {node = LeafNull} = (genMovXsm r "0", r, remainingRegs, labels) Args {regsFree = regsFree, labels = labels} = a genCode a@Args {node = (LeafVar var resolver)} = (code, r, rs, labels) where - Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst, tTable = tt} = a - (code, r, rs) = genValResolveCode var resolver regsFree gst lst tt + Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst} = a + (code, r, rs) = genValResolveCode var resolver regsFree gst lst genCode a@Args {node = (LeafFn name params)} = (genFnCallXsm usedRegs fnLabel argCodes returnReg, returnReg, rs, labels) where Args {regsFree = regsFree, labels = labels, gSymTable = gst} = a @@ -139,8 +133,8 @@ genCode a@Args {node = (LeafFn name params)} = (genFnCallXsm usedRegs fnLabel ar -- Operator Nodes genCode a@Args {node = (NodeRef (LeafVar var resolver))} = (argCode, r, rem, labels) where - Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst, tTable = tt} = a - (argCode, r, rem) = genAddrResolveCode var resolver regsFree gst lst tt + Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst} = a + (argCode, r, rem) = genAddrResolveCode var resolver regsFree gst lst genCode a@Args {node = (NodeArmc op l r)} = (lCode ++ rCode ++ genArmcXsm op lReg rReg, lReg, regRemaining, labels) where (lCode, lReg, regRemaining, _) = genCode a {node = l} @@ -209,9 +203,9 @@ genCode a@Args {node = NodeCont, regsFree = fr, labels = lb, blockLabels = bl} = genCode a@Args {node = (NodeAssign (LeafVar var varResolver) r)} = (code, "", regsFree, labels) where (rCode, rReg, regs2, _) = genCode a {node = r} - (lCode, lReg, _) = genAddrResolveCode var varResolver regs2 gst lst tt + (lCode, lReg, _) = genAddrResolveCode var varResolver regs2 gst lst code = rCode ++ lCode ++ genMovXsm (accessMem lReg) rReg - Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst, tTable = tt} = a + Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst} = a genCode a@Args {node = (NodeConn l r)} = (lCode ++ rCode, rReg, regsFree, remainingLabels) where (lCode, _, _, labels2) = genCode a {node = l} @@ -232,10 +226,10 @@ genCode a@Args {node = (NodeWrite arg)} = (argCode ++ genLibXsm usedRegs "Write" (retReg, regsRem) = getReg regsFree genCode a@Args {node = (NodeRead arg)} = (argCode ++ genLibXsm usedRegs "Read" libArgs retReg, retReg, regsRem, labels) where - Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst, tTable = tt} = a + Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst} = a usedRegs = getRegsUsed regsFree (LeafVar var varResolver) = arg - (argCode, argReg, regRem) = genAddrResolveCode var varResolver regsRem gst lst tt + (argCode, argReg, regRem) = genAddrResolveCode var varResolver regsRem gst lst libArgs = (ValInt $ -1, Reg argReg, None) (retReg, regsRem) = getReg regsFree genCode a@Args {node = NodeInitialize} = (genLibXsm usedRegs "Heapset" libArgs retReg, retReg, regsRem, labels) @@ -244,14 +238,13 @@ genCode a@Args {node = NodeInitialize} = (genLibXsm usedRegs "Heapset" libArgs r usedRegs = getRegsUsed regsFree libArgs = (None, None, None) (retReg, regsRem) = getReg regsFree -genCode a@Args {node = (NodeAlloc var@(LeafVar vName vRes))} = (code, "", regsFree, labels) +genCode a@Args {node = (NodeAlloc var@(LeafVar vName vRes) size)} = (code, "", regsFree, labels) where - Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst, tTable = tTable} = a + Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst} = a usedRegs = getRegsUsed regsFree - varSize = getTypeSize tTable $ findVarType gst lst tTable var - libArgs = (ValInt varSize, None, None) + libArgs = (ValInt size, None, None) (retReg, regsRem) = getReg regsFree - (lCode, lReg, _) = genAddrResolveCode vName vRes regsRem gst lst tTable + (lCode, lReg, _) = genAddrResolveCode vName vRes regsRem gst lst code = genLibXsm usedRegs "Alloc" libArgs retReg ++ lCode ++ genMovXsm (accessMem lReg) retReg genCode a@Args {node = (NodeFree var)} = (varCode ++ genLibXsm usedRegs "Free" libArgs retReg, retReg, regsRem, labels) where @@ -270,8 +263,8 @@ type FDef = (String, String, [String], LSymbolTable, SyntaxTree) -- Generates code for a function -- FDef -> GSymbolTable -> labels -> (remainingLabels, code) -genFnCode :: FDef -> GSymbolTable -> TypeTable -> [String] -> ([String], String) -genFnCode (_, name, params, lSym, ast) gSym tTable labels = +genFnCode :: FDef -> GSymbolTable -> [String] -> ([String], String) +genFnCode (_, name, params, lSym, ast) gSym labels = ( remainingLabels, genLabelXsm label ++ genStackXsm PUSH "BP" @@ -297,19 +290,18 @@ genFnCode (_, name, params, lSym, ast) gSym tTable labels = labels = labels, blockLabels = Nothing, gSymTable = gSym, - lSymTable = lSym, - tTable = tTable + lSymTable = lSym } lVarRelCode = concat $ replicate lVarCount (genStackXsm POP "R0") --- GSymbolTable -> sp -> typetable -> fDecls -> mainBlock -> code -codeGen :: GSymbolTable -> Int -> TypeTable -> [FDef] -> (LSymbolTable, SyntaxTree) -> String -codeGen gTable sp tTable fDecls main = header ++ code +-- GSymbolTable -> sp -> fDecls -> mainBlock -> code +codeGen :: GSymbolTable -> Int -> [FDef] -> (LSymbolTable, SyntaxTree) -> String +codeGen gTable sp fDecls main = header ++ code where header = unlines $ map show [0, 2056, 0, 0, 0, 0, 0, 0] - (labelsRem, codeList) = mapAccumL (\a b -> genFnCode b gTable tTable a) ["L" ++ show i | i <- [0, 1 ..]] fDecls + (labelsRem, codeList) = mapAccumL (\a b -> genFnCode b gTable a) ["L" ++ show i | i <- [0, 1 ..]] fDecls (mainLSym, mainAst) = main - (_, mainCode) = genFnCode ("int", "main", [], mainLSym, mainAst) gTable tTable labelsRem + (_, mainCode) = genFnCode ("int", "main", [], mainLSym, mainAst) gTable labelsRem (initCode, _, _, _) = genCode Args {node = LeafFn "main" [], regsFree = allRegs, gSymTable = gTable} labelledCode = genMovXsm "SP" (show sp) ++ initCode ++ "INT 10\n" ++ concat codeList ++ mainCode -- code = labelledCode diff --git a/Stage6/Compiler.hs b/Stage6/Compiler.hs index 6f6fab1..6952fe9 100644 --- a/Stage6/Compiler.hs +++ b/Stage6/Compiler.hs @@ -19,11 +19,10 @@ main = do args <- getArgs inputFile <- openFile (head args) ReadMode fileContents <- hGetContents inputFile - let (tTable, gTable, sp, fDecl, main) = parseTokens (scanTokens fileContents) + let (gTable, sp, fDecl, main) = parseTokens (scanTokens fileContents) -- print gTable - -- print tTable -- print fDecl -- let (_, mainAst) = main in putStr $ prettyPrint mainAst - let code = codeGen gTable sp tTable fDecl main + let code = codeGen gTable sp fDecl main createOutputFile code hClose inputFile diff --git a/Stage6/Parser.y b/Stage6/Parser.y index 58c832d..0de3b48 100644 --- a/Stage6/Parser.y +++ b/Stage6/Parser.y @@ -167,7 +167,7 @@ Stmt : Variable '=' RVal ';' {% let (t, v) = $3 in | BREAK ';' { NodeBreak } | CONTINUE ';' { NodeCont } | FnCall ';' { $1 } - | Variable '=' ALLOC '(' ')' ';' {% varType $1 >>= userTypeCheck >> return (NodeAlloc $1) } + | Variable '=' ALLOC '(' ')' ';' {% varType $1 >>= \t -> (userTypeCheck t >> typeSize t) >>= \s -> return (NodeAlloc $1 s) } E2 : E '+' E { NodeArmc '+' $1 $3 } | E '-' E { NodeArmc '-' $1 $3 } @@ -202,7 +202,7 @@ Variable : id {% symCheck (isUnit) $1 >> return (LeafV | id '[' E ']' {% symCheck (isArr) $1 >> return (LeafVar $1 (Index $3)) } | id '['E']' '['E']' {% symCheck (isArr2) $1 >> return (LeafVar $1 (Index2D $3 $6)) } | '*' id {% symCheck (isPtr) $2 >> return (LeafVar $2 Deref) } - | DotField {% let n:d = $1 in (dotSymCheck n d >> return(LeafVar n (Dot d))) } + | DotField {% (let n:ds = $1 in dotSymCheck n ds >>= \di -> return (LeafVar n (Dot di))) } DotField : DotField '.' id { $1 ++ [$3] } | id '.' id { [$1, $3] } @@ -219,7 +219,7 @@ Main: MAIN {% saveMainFn } parseError t = error $ "Parse error: " ++ show t -parseTokens tokenStream = (tTable, gSymFull, sp, fDecl, main) +parseTokens tokenStream = (gSymFull, sp, fDecl, main) where ((sp, fDecl, main), (tTable, gSymTable, _, _)) = runState (parse tokenStream) startState gSymFull = Map.insertWith (error "Main function declared twice") "main" (Func "int" [] "main") gSymTable diff --git a/Stage6/ParserState.hs b/Stage6/ParserState.hs index 4e41794..73a88d9 100644 --- a/Stage6/ParserState.hs +++ b/Stage6/ParserState.hs @@ -1,6 +1,6 @@ module ParserState where -import Control.Monad.State (MonadState (get, put), State, unless) +import Control.Monad.State (MonadState (get, put), State) import Data.Bifunctor (second) import qualified Data.Map as Map import SymbolTable @@ -110,6 +110,14 @@ fnCallTypeCheck name params = do else error $ "Function call doesnt match definition: " ++ name ++ show (map fst params) _ -> error $ "Function call is invalid: " ++ name +-- Typechecks and returns modified index dotfields +dotSymCheck :: String -> [String] -> State ParserState [Int] +dotSymCheck symName dots = do + (tTable, _, _, symTab) <- get + case Map.lookup symName symTab of + Just s -> return $ dotStrToIndex tTable (getSymbolType s) dots + Nothing -> error $ "Variable does not exist : " ++ symName + retTypeCheck :: String -> State ParserState () retTypeCheck t = do (_, _, cFn, _) <- get @@ -128,13 +136,6 @@ userTypeCheck tName = do Just _ -> return () Nothing -> error $ "Cannot do heap operations on " ++ tName -dotSymCheck :: String -> [String] -> State ParserState () -dotSymCheck symName dots = do - (tTable, _, _, symTab) <- get - case Map.lookup symName symTab of - Just s -> unless (null (resolveDotType tTable (getSymbolType s) dots)) (return ()) - Nothing -> error $ "Variable does not exist : " ++ symName - intCheck :: SyntaxTree -> State ParserState SyntaxTree intCheck n = do (tt, _, _, symTab) <- get @@ -152,6 +153,11 @@ varType n = do (tt, _, _, symTab) <- get return $ getVarType symTab tt n +typeSize :: String -> State ParserState Int +typeSize tName = do + (tt, _, _, _) <- get + return $ getTypeSize tt tName + fnType :: SyntaxTree -> State ParserState String fnType n = do (_, _, _, symTab) <- get diff --git a/Stage6/SyntaxTree.hs b/Stage6/SyntaxTree.hs index 9fee330..8041e8d 100644 --- a/Stage6/SyntaxTree.hs +++ b/Stage6/SyntaxTree.hs @@ -10,7 +10,7 @@ data VarResolve | Deref | Index SyntaxTree | Index2D SyntaxTree SyntaxTree - | Dot [String] + | Dot [Int] deriving (Show) data SyntaxTree @@ -22,7 +22,7 @@ data SyntaxTree | NodeRead SyntaxTree | NodeWrite SyntaxTree | NodeInitialize - | NodeAlloc SyntaxTree + | NodeAlloc SyntaxTree Int | NodeFree SyntaxTree | NodeArmc Char SyntaxTree SyntaxTree | NodeBool String SyntaxTree SyntaxTree @@ -65,7 +65,7 @@ getFnType st (NodeRead _) = "int" getFnType st (NodeWrite _) = "int" getFnType st NodeInitialize = "int" getFnType st (NodeFree _) = "int" -getFnType st (NodeAlloc _) = "int" +getFnType st (NodeAlloc _ _) = "int" getFnType _ _ = error "Not a function" toDataTree :: SyntaxTree -> Tree String @@ -79,7 +79,7 @@ toDataTree t = case t of NodeWhile cond bl -> Node "While" [toDataTree cond, toDataTree bl] NodeRead t -> Node "Read" [toDataTree t] NodeWrite t -> Node "Write" [toDataTree t] - NodeAlloc t -> Node "Alloc" [toDataTree t] + NodeAlloc t s -> Node ("Alloc " ++ show s) [toDataTree t] NodeFree t -> Node "Free" [toDataTree t] _ -> Node (show t) [] diff --git a/Stage6/TypeTable.hs b/Stage6/TypeTable.hs index 5b73f40..9bb9d28 100644 --- a/Stage6/TypeTable.hs +++ b/Stage6/TypeTable.hs @@ -10,13 +10,23 @@ type TypeTable = Map.Map String [Field] -- Name -> TypeInfo -- | Check if a list of dot access is valid on a given type and returns final type -- | TypeTable -> startType -> [DotList] -> FinalType -resolveDotType :: TypeTable -> String -> [String] -> String -resolveDotType tTable = foldl' childType +resolveDotType :: TypeTable -> String -> [Int] -> String +resolveDotType tTable = foldl' (\pType cIndex -> fst ((tTable Map.! pType) !! cIndex)) + +-- | Converts a dot list of strings to field indices +-- | TypeTable -> startType -> stringFields -> indexFields +dotStrToIndex :: TypeTable -> String -> [String] -> [Int] +dotStrToIndex tTable startType fields = intFields where - childType :: String -> String -> String - childType pType cName = case find ((cName ==) . snd) (tTable Map.! pType) of - Just (tName, _) -> tName - Nothing -> error $ "Type " ++ pType ++ " does not contain child " ++ cName + mapFn :: String -> String -> (String, Int) + mapFn pType cName = (cType, childIndex) + where + pFields = tTable Map.! pType + (childIndex, (cType, _)) = case findIndex ((cName ==) . snd) pFields of + Just i -> (i, pFields !! i) + Nothing -> error $ "Type " ++ pType ++ " does not contain child " ++ cName + + (_, intFields) = mapAccumL mapFn startType fields -- | Returns the size of a given type string getTypeSize :: TypeTable -> String -> Int