@@ -20,7 +20,7 @@ import LLVM.General.Target ( TargetMachine
21import LLVM.General.AST.DataLayout
21import LLVM.General.AST.DataLayout
22import qualified LLVM.General.PassManager as PM
22import qualified LLVM.General.PassManager as PM
23−import qualified LLVM.General.Module as M
23+import qualified LLVM.General.Module as MO
24import qualified LLVM.General.AST.IntegerPredicate as IPred
24import qualified LLVM.General.AST.IntegerPredicate as IPred
25import qualified LLVM.General.AST.Linkage as L
25import qualified LLVM.General.AST.Linkage as L
26import qualified LLVM.General.AST.Visibility as V
26import qualified LLVM.General.AST.Visibility as V
@@ -36,9 +36,9 @@ import qualified LLVM.General.CodeGenOpt as CGO
36import Data.List
36import Data.List
37import Data.Maybe
37import Data.Maybe
38import Data.Word
38import Data.Word
39−import Data.Set (Set)
39+import Data.Map (Map)
40−import qualified Data.Set as S
41import qualified Data.Map as M
40import qualified Data.Map as M
41+import qualified Data.Set as S
42import qualified Data.Vector.Unboxed as V
42import qualified Data.Vector.Unboxed as V
43import Control.Applicative
43import Control.Applicative
44import Control.Monad.RWS
44import Control.Monad.RWS
@@ -70,7 +70,7 @@ codegenLLVM defs triple cpu optimize file outty = withContext $ \context -> do
70 withTargetMachine target triple cpu S.empty options R.Default CM.Default CGO.Default $ \tm ->
70 withTargetMachine target triple cpu S.empty options R.Default CM.Default CGO.Default $ \tm ->
71 do layout <- getTargetMachineDataLayout tm
71 do layout <- getTargetMachineDataLayout tm
72 let ast = codegen (Target triple layout) (map snd defs)
72 let ast = codegen (Target triple layout) (map snd defs)
73− result <- runErrorT . M.withModuleFromAST context ast $ \m ->
73+ result <- runErrorT . MO.withModuleFromAST context ast $ \m ->
74 do let opts = PM.defaultCuratedPassSetSpec
74 do let opts = PM.defaultCuratedPassSetSpec
75 { PM.optLevel = Just optimize
75 { PM.optLevel = Just optimize
76 , PM.simplifyLibCalls = Just True
76 , PM.simplifyLibCalls = Just True
@@ -85,9 +85,9 @@ codegenLLVM defs triple cpu optimize file outty = withContext $ \context -> do
85failInIO :: ErrorT String IO a -> IO a
85failInIO :: ErrorT String IO a -> IO a
86failInIO = either fail return <=< runErrorT
86failInIO = either fail return <=< runErrorT
88−outputModule :: TargetMachine -> FilePath -> OutputType -> M.Module -> IO ()
88+outputModule :: TargetMachine -> FilePath -> OutputType -> MO.Module -> IO ()
89−outputModule _ file Raw m = failInIO $ M.writeBitcodeToFile file m
89+outputModule _ file Raw m = failInIO $ MO.writeBitcodeToFile file m
90−outputModule tm file Object m = failInIO $ M.writeObjectToFile tm file m
90+outputModule tm file Object m = failInIO $ MO.writeObjectToFile tm file m
91outputModule tm file Executable m = withTmpFile $ \obj -> do
91outputModule tm file Executable m = withTmpFile $ \obj -> do
92 outputModule tm obj Object m
92 outputModule tm obj Object m
93 cc <- getCC
93 cc <- getCC
@@ -193,6 +193,7 @@ initDefs tgt =
193 , exfun "__idris_gmpFree" VoidType [ptrI8, intPtr] False
193 , exfun "__idris_gmpFree" VoidType [ptrI8, intPtr] False
194 , exfun "__idris_strRev" ptrI8 [ptrI8] False
194 , exfun "__idris_strRev" ptrI8 [ptrI8] False
195 , exfun "strtoll" (IntegerType 64) [ptrI8, PointerType ptrI8 (AddrSpace 0), IntegerType 32] False
195 , exfun "strtoll" (IntegerType 64) [ptrI8, PointerType ptrI8 (AddrSpace 0), IntegerType 32] False
196+ , exfun "putErr" VoidType [ptrI8] False
196 , exVar (stdinName tgt) ptrI8
197 , exVar (stdinName tgt) ptrI8
197 , exVar (stdoutName tgt) ptrI8
198 , exVar (stdoutName tgt) ptrI8
198 , exVar (stderrName tgt) ptrI8
199 , exVar (stderrName tgt) ptrI8
@@ -244,7 +245,7 @@ getStdErr = ConstantOperand . C.GlobalReference . Name . stderrName <$> asks tar
244codegen :: Target -> [SDecl] -> Module
245codegen :: Target -> [SDecl] -> Module
245codegen tgt defs = Module "idris" (Just . dataLayout $ tgt) (Just . triple $ tgt) (initDefs tgt ++ globals ++ gendefs)
246codegen tgt defs = Module "idris" (Just . dataLayout $ tgt) (Just . triple $ tgt) (initDefs tgt ++ globals ++ gendefs)
247− (gendefs, _, globals) = runRWS (mapM cgDef defs) tgt 0
248+ (gendefs, _, globals) = runRWS (mapM cgDef defs) tgt initialMGS
249valueType :: Type
250valueType :: Type
250valueType = NamedTypeReference (Name "valTy")
251valueType = NamedTypeReference (Name "valTy")
@@ -264,24 +265,34 @@ conType nargs = StructureType False
264 , ArrayType nargs (PointerType valueType (AddrSpace 0))
265 , ArrayType nargs (PointerType valueType (AddrSpace 0))
268+data MGS = MGS { mgsNextGlobalName :: Word
269+ , mgsForeignSyms :: Map String (FType, [FType])
267−type Modgen = RWS Target [Definition] Word
272+type Modgen = RWS Target [Definition] MGS
275+initialMGS = MGS { mgsNextGlobalName = 0
276+ , mgsForeignSyms = M.empty
269cgDef :: SDecl -> Modgen Definition
279cgDef :: SDecl -> Modgen Definition
270cgDef (SFun name argNames _ expr) = do
280cgDef (SFun name argNames _ expr) = do
271− nextGlobal <- get
281+ nextGlobal <- gets mgsNextGlobalName
282+ existingForeignSyms <- gets mgsForeignSyms
272 tgt <- ask
283 tgt <- ask
273− let (_, CGS { nextGlobalName = nextGlobal' }, (allocas, bbs, globals)) =
284+ let (_, CGS { nextGlobalName = nextGlobal', foreignSyms = foreignSyms' }, (allocas, bbs, globals)) =
274 runRWS (do r <- cgExpr expr
285 runRWS (do r <- cgExpr expr
275 case r of
286 case r of
276 Nothing -> terminate $ Unreachable []
287 Nothing -> terminate $ Unreachable []
277 Just r' -> terminate $ Ret (Just r') [])
288 Just r' -> terminate $ Ret (Just r') [])
278 (CGR tgt (show name))
289 (CGR tgt (show name))
279− (CGS 0 nextGlobal (Name "begin") [] (map (Just . LocalReference . Name . show) argNames) S.empty)
290+ (CGS 0 nextGlobal (Name "begin") [] (map (Just . LocalReference . Name . show) argNames) existingForeignSyms)
280 entryTerm = case bbs of
291 entryTerm = case bbs of
281 [] -> Do $ Ret Nothing []
292 [] -> Do $ Ret Nothing []
282 BasicBlock n _ _:_ -> Do $ Br n []
293 BasicBlock n _ _:_ -> Do $ Br n []
283 tell globals
294 tell globals
284− put nextGlobal'
295+ put (MGS { mgsNextGlobalName = nextGlobal', mgsForeignSyms = foreignSyms' })
285 return . GlobalDefinition $ functionDefaults
296 return . GlobalDefinition $ functionDefaults
286 { G.linkage = L.Internal
297 { G.linkage = L.Internal
287 , G.callingConvention = CC.Fast
298 , G.callingConvention = CC.Fast
@@ -306,7 +317,7 @@ data CGS = CGS { nextName :: Word
306 , currentBlockName :: Name
317 , currentBlockName :: Name
307 , instAccum :: [Named Instruction]
318 , instAccum :: [Named Instruction]
308 , lexenv :: Env
319 , lexenv :: Env
309− , foreignSyms :: Set String
320+ , foreignSyms :: Map String (FType, [FType])
312data CGR = CGR { target :: Target
323data CGR = CGR { target :: Target
@@ -524,10 +535,10 @@ cgExpr (SOp fn args) = do
524 Just ops -> Just <$> cgOp fn ops
535 Just ops -> Just <$> cgOp fn ops
525 Nothing -> return Nothing
536 Nothing -> return Nothing
526cgExpr SNothing = return . Just . ConstantOperand $ nullValue
537cgExpr SNothing = return . Just . ConstantOperand $ nullValue
527−cgExpr (SError msg) = do -- TODO: Print message
538+cgExpr (SError msg) = do
528 str <- addGlobal' (ArrayType (2 + fromIntegral (length msg)) (IntegerType 8))
539 str <- addGlobal' (ArrayType (2 + fromIntegral (length msg)) (IntegerType 8))
529 (cgConst' (TT.Str (msg ++ "\n")))
540 (cgConst' (TT.Str (msg ++ "\n")))
530− inst' $ simpleCall "putStr" [ConstantOperand $ C.GetElementPtr True str [ C.Int 32 0
541+ inst' $ simpleCall "putErr" [ConstantOperand $ C.GetElementPtr True str [ C.Int 32 0
531 , C.Int 32 0]]
542 , C.Int 32 0]]
532 inst' Call { isTailCall = True
543 inst' Call { isTailCall = True
533 , callingConvention = CC.C
544 , callingConvention = CC.C
@@ -799,9 +810,11 @@ addGlobal' ty val = do
799ensureCDecl :: String -> FType -> [FType] -> Codegen Operand
810ensureCDecl :: String -> FType -> [FType] -> Codegen Operand
800ensureCDecl name rty argtys = do
811ensureCDecl name rty argtys = do
801 syms <- gets foreignSyms
812 syms <- gets foreignSyms
802− unless (S.member name syms) $
813+ case M.lookup name syms of
803− do addGlobal (ffunDecl name rty argtys)
814+ Nothing -> do addGlobal (ffunDecl name rty argtys)
804− modify $ \s -> s { foreignSyms = S.insert name (foreignSyms s) }
815+ modify $ \s -> s { foreignSyms = M.insert name (rty, argtys) (foreignSyms s) }
816+ Just (rty', argtys') -> unless (rty == rty' && argtys == argtys') . fail $
817+ "Mismatched type declarations for foreign symbol \"" ++ name ++ "\": " ++ show (rty, argtys) ++ " vs " ++ show (rty', argtys')
805 return $ ConstantOperand (C.GlobalReference (Name name))
818 return $ ConstantOperand (C.GlobalReference (Name name))
807ffunDecl :: String -> FType -> [FType] -> Global
820ffunDecl :: String -> FType -> [FType] -> Global