summaryrefslogtreecommitdiff
path: root/codegen.hs
diff options
context:
space:
mode:
Diffstat (limited to 'codegen.hs')
-rw-r--r--codegen.hs78
1 files changed, 58 insertions, 20 deletions
diff --git a/codegen.hs b/codegen.hs
index 0deb959..1df87b4 100644
--- a/codegen.hs
+++ b/codegen.hs
@@ -8,6 +8,7 @@ import Data.Maybe
import qualified Data.Map.Strict as Map
import qualified LLVM.General.AST.Type as A
import qualified LLVM.General.AST.Global as A.G
+import qualified LLVM.General.AST.CallingConvention as A.CC
import qualified LLVM.General.AST.Constant as A.C
import qualified LLVM.General.AST.Float as A.F
-- import qualified LLVM.General.AST.Operand as A
@@ -34,6 +35,7 @@ data GenState
,definitions :: [A.Definition]
,variables :: Map.Map Name (Type, LLName)
,globalVariables :: Map.Map Name (Type, LLName)
+ ,globalFunctions :: Map.Map Name (Type, LLName)
,stringLiterals :: [(LLName, String)]}
deriving (Show)
@@ -46,6 +48,7 @@ initialGenState
,definitions = []
,variables = Map.empty
,globalVariables = Map.empty
+ ,globalFunctions = Map.empty
,stringLiterals = []}
newtype CGMonad a = CGMonad {unMon :: ExceptT String (State GenState) a}
@@ -109,6 +112,10 @@ setGlobalVar :: Name -> LLName -> Type -> CGMonad ()
setGlobalVar name label t = do
state $ \s -> ((), s {globalVariables = Map.insert name (t, label) $ globalVariables s})
+setGlobalFunction :: Name -> LLName -> Type -> CGMonad ()
+setGlobalFunction name label t = do
+ state $ \s -> ((), s {globalFunctions = Map.insert name (t, label) $ globalFunctions s})
+
lookupVar :: Name -> CGMonad (Type, LLName)
lookupVar name | trace ("Looking up var " ++ name) False = undefined
lookupVar name = do
@@ -122,6 +129,9 @@ lookupVar name = do
lookupGlobalVar :: Name -> CGMonad (Type, LLName)
lookupGlobalVar name = liftM (fromJust . Map.lookup name . globalVariables) get
+lookupGlobalFunction :: Name -> CGMonad (Type, LLName)
+lookupGlobalFunction name = liftM (fromJust . Map.lookup name . globalFunctions) get
+
addStringLiteral :: String -> CGMonad LLName
addStringLiteral str = do
name <- getNewName "str"
@@ -167,8 +177,8 @@ codegen :: Program -- Program to compile
codegen prog name fname = do
(defs, st) <- runCGMonad $ do
defs <- generateDefs prog
- traceShow defs $ return ()
- liftM stringLiterals get >>= flip traceShow (return ())
+ -- traceShow defs $ return ()
+ -- liftM stringLiterals get >>= flip traceShow (return ())
return defs
traceShow st $ return ()
@@ -185,19 +195,22 @@ generateDefs prog
= liftM concat $ sequence $ [genGlobalVars prog, genFunctions prog, genStringLiterals]
genGlobalVars :: Program -> CGMonad [A.Definition]
-genGlobalVars (Program decs) = mapM gen $ filter isDecVariable decs
+genGlobalVars (Program decs) = liftM (mapMaybe id) $ mapM gen decs
where
- gen :: Declaration -> CGMonad A.Definition
+ gen :: Declaration -> CGMonad (Maybe A.Definition)
gen (DecVariable t n Nothing) = do
setGlobalVar n n t
- return $ A.GlobalDefinition $
+ return $ Just $ A.GlobalDefinition $
A.globalVariableDefaults {
A.G.name = A.Name n,
A.G.type' = toLLVMType t,
A.G.initializer = Just $ initializerFor t
}
gen (DecVariable _ _ (Just _)) = throwError $ "Initialised global variables not supported yet"
- gen _ = undefined
+ gen (DecFunction rt n a _) = do
+ setGlobalFunction n n (TypeFunc rt (map fst a))
+ return Nothing
+ gen _ = return Nothing
genStringLiterals :: CGMonad [A.Definition]
genStringLiterals = liftM stringLiterals get >>= return . map gen
@@ -211,9 +224,9 @@ genStringLiterals = liftM stringLiterals get >>= return . map gen
}
genFunctions :: Program -> CGMonad [A.Definition]
-genFunctions (Program decs) = mapM gen $ filter isDecFunction decs
+genFunctions (Program decs) = liftM (mapMaybe id) $ mapM gen decs
where
- gen :: Declaration -> CGMonad A.Definition
+ gen :: Declaration -> CGMonad (Maybe A.Definition)
gen dec@(DecFunction rettype name args body) = do
setCurrentFunction dec
firstbb <- genBlock' body
@@ -221,13 +234,14 @@ genFunctions (Program decs) = mapM gen $ filter isDecFunction decs
blockmap <- liftM allBlocks get
let bbs' = map snd $ filter (\x -> fst x /= firstbb) $ Map.toList blockmap
bbs = fromJust (Map.lookup firstbb blockmap) : bbs'
- return $ A.GlobalDefinition $ A.functionDefaults {
+ state $ \s -> ((), s {allBlocks = Map.empty})
+ return $ Just $ A.GlobalDefinition $ A.functionDefaults {
A.G.returnType = toLLVMType rettype,
A.G.name = A.Name name,
A.G.parameters = ([A.Parameter (toLLVMType t) (A.Name n) [] | (t,n) <- args], False),
A.G.basicBlocks = bbs
}
- gen _ = undefined
+ gen _ = return Nothing
@@ -275,7 +289,11 @@ genSingle (StAssignment name expr) following = do
ref <- variableStoreOperand name
void $ addInstr $ A.Store False ref oper' Nothing 0 []
return bb
-genSingle (StReturn expr) _ = do
+genSingle (StReturn Nothing) _ = do
+ bb <- newBlock
+ setTerminator $ A.Ret Nothing []
+ return bb
+genSingle (StReturn (Just expr)) _ = do
bb <- newBlock
oper <- genExpression expr
rettype <- liftM (typeOf . currentFunction) get
@@ -316,6 +334,8 @@ genExpression (ExBinOp bo e1 e2 (Just t)) = do
TypeDouble -> addInstr $ A.FAdd A.NoFastMathFlags e1op' e2op' []
(TypePtr _) -> addInstr $ A.Add False False e1op' e2op' []
(TypeName _) -> undefined
+ (TypeFunc _ _) -> throwError $ "Plus '+' operator not defined on function pointers"
+ TypeVoid -> undefined
return $ A.LocalReference (toLLVMType t) (A.Name label)
Minus -> do
e1op' <- castOperand e1op t
@@ -327,6 +347,8 @@ genExpression (ExBinOp bo e1 e2 (Just t)) = do
TypeDouble -> addInstr $ A.FSub A.NoFastMathFlags e1op' e2op' []
(TypePtr _) -> addInstr $ A.Sub False False e1op' e2op' []
(TypeName _) -> undefined
+ (TypeFunc _ _) -> throwError $ "Minus '-' operator not defined on function pointers"
+ TypeVoid -> undefined
return $ A.LocalReference (toLLVMType t) (A.Name label)
Divide -> do
e1op' <- castOperand e1op t
@@ -338,6 +360,8 @@ genExpression (ExBinOp bo e1 e2 (Just t)) = do
TypeDouble -> addInstr $ A.FDiv A.NoFastMathFlags e1op' e2op' []
(TypePtr _) -> throwError $ "Modulo '%' operator not defined on pointers"
(TypeName _) -> undefined
+ (TypeFunc _ _) -> throwError $ "Divide '/' operator not defined on function pointers"
+ TypeVoid -> undefined
return $ A.LocalReference (toLLVMType t) (A.Name label)
Modulo -> do
e1op' <- castOperand e1op t
@@ -349,6 +373,8 @@ genExpression (ExBinOp bo e1 e2 (Just t)) = do
TypeDouble -> addInstr $ A.FRem A.NoFastMathFlags e1op' e2op' []
(TypePtr _) -> throwError $ "Modulo '%' operator not defined on pointers"
(TypeName _) -> undefined
+ (TypeFunc _ _) -> throwError $ "Modulo '%' operator not defined on function pointers"
+ TypeVoid -> undefined
return $ A.LocalReference (toLLVMType t) (A.Name label)
Equal -> do
sharedType <- commonTypeM (fromJust (exTypeOf e1)) (fromJust (exTypeOf e2))
@@ -395,6 +421,8 @@ genExpression (ExUnOp uo e1 (Just t)) = do
TypeDouble -> addInstr $ A.FSub A.NoFastMathFlags (A.ConstantOperand (A.C.Float (A.F.Double 0))) e1op []
(TypePtr _) -> throwError $ "Negate '-' operator not defined on a pointer"
(TypeName _) -> undefined
+ (TypeFunc _ _) -> throwError $ "Negate '-' operator not defined on a function pointer"
+ TypeVoid -> undefined
return $ A.LocalReference (toLLVMType t) (A.Name label)
_ -> throwError $ "Unary operator " ++ pshow uo ++ " not implemented"
genExpression ex = throwError $ "Expression '" ++ pshow ex ++ "' not implemented"
@@ -416,6 +444,23 @@ literalToOperand (LitString s) (TypePtr (TypeInt 8)) = do
label <- addInstr $ A.Load False loadoper Nothing 0 []
return $ A.LocalReference (A.ptr A.i8) (A.Name label)
literalToOperand (LitString _) _ = undefined
+literalToOperand (LitCall n args) _ = do
+ ((TypeFunc rt ats), lname) <- lookupGlobalFunction n
+ let processArgs :: [Expression] -> [Type] -> CGMonad [A.Operand]
+ processArgs [] [] = return []
+ processArgs [] _ = undefined
+ processArgs _ [] = undefined
+ processArgs (ex:exs) (t:ts) = do
+ first <- genExpression ex >>= flip castOperand t
+ rest <- processArgs exs ts
+ return $ first : rest
+ rargs <- processArgs args ats
+ let argpairs = map (\a -> (a,[])) rargs
+ foper = A.ConstantOperand $
+ A.C.GlobalReference (A.FunctionType (toLLVMType rt) (map toLLVMType ats) False)
+ (A.Name lname)
+ label <- addInstr $ A.Call Nothing A.CC.C [] (Right foper) argpairs [] []
+ return $ A.LocalReference (toLLVMType rt) (A.Name label)
literalToOperand lit _ = throwError $ "Literal '" ++ pshow lit ++ "' not implemented"
castOperand :: A.Operand -> Type -> CGMonad A.Operand
@@ -533,17 +578,10 @@ toLLVMType TypeFloat = A.float
toLLVMType TypeDouble = A.double
toLLVMType (TypePtr t) = A.ptr $ toLLVMType t
toLLVMType (TypeName _) = undefined
+toLLVMType (TypeFunc r a) = A.FunctionType (toLLVMType r) (map toLLVMType a) False
+toLLVMType TypeVoid = A.VoidType
initializerFor :: Type -> A.C.Constant
initializerFor (TypeInt s) = A.C.Int (fromIntegral s) 0
initializerFor (TypeUInt s) = A.C.Int (fromIntegral s) 0
initializerFor _ = undefined
-
-
-isDecVariable :: Declaration -> Bool
-isDecVariable (DecVariable {}) = True
-isDecVariable _ = False
-
-isDecFunction :: Declaration -> Bool
-isDecFunction (DecFunction {}) = True
-isDecFunction _ = False