ddc-core-llvm-0.4.2.1: DDC/Core/Llvm/Convert/Context.hs
module DDC.Core.Llvm.Convert.Context
( Context (..)
, extendKindEnv, extendsKindEnv
, extendTypeEnv, extendsTypeEnv
, ExpContext (..)
, AltResult (..)
, takeVarOfContext
, takeNonVoidVarOfContext)
where
import DDC.Core.Salt.Platform
import DDC.Core.Llvm.Metadata.Tbaa
import DDC.Core.Llvm.Convert.Base
import DDC.Type.Exp
import DDC.Llvm.Syntax
import DDC.Type.Env (KindEnv, TypeEnv)
import Data.Sequence (Seq)
import Data.Set (Set)
import Data.Map (Map)
import qualified DDC.Core.Salt as A
import qualified DDC.Core.Module as C
import qualified DDC.Core.Exp as C
import qualified DDC.Type.Env as Env
---------------------------------------------------------------------------------------------------
-- | Context of an Salt to LLVM conversion.
data Context
= Context
{ -- | The platform that we're converting to,
-- this sets the pointer width.
contextPlatform :: Platform
-- | Surrounding module.
, contextModule :: C.Module () A.Name
-- | The top-level kind environment.
, contextKindEnvTop :: KindEnv A.Name
-- | The top-level type environment.
, contextTypeEnvTop :: TypeEnv A.Name
-- | Names of imported supers that are defined in external modules.
-- These are directly callable in the object code.
, contextImports :: Set A.Name
-- | Names of local supers that are defined in the current module.
-- These are directly callable in the object code.
, contextSupers :: Set A.Name
-- | Current kind environment.
, contextKindEnv :: KindEnv A.Name
-- | Current type environment.
, contextTypeEnv :: TypeEnv A.Name
-- | Map between core level variable names and LLVM names.
, contextNames :: Map A.Name Var
-- | Super meta data
, contextMDSuper :: MDSuper
-- | C library functions that are used directly by the generated code without
-- having an import declaration in the header of the converted module.
, contextPrimDecls :: Map String FunctionDecl
-- | Re-bindings of top-level supers.
-- This is used to handle let-expressions like 'f = g [t]' where
-- 'g' is a top-level super. See [Note: Binding top-level supers]
-- Maps the right hand variable to the left hand one, eg g -> f,
-- along with its type arguments.
, contextSuperBinds
:: Map A.Name (A.Name, [C.Type A.Name])
-- Functions to convert the various parts of the AST.
-- We tie the recursive knot though this Context type so that
-- we can split the implementation into separate non-recursive modules.
, contextConvertBody
:: Context -> ExpContext
-> Seq Block -> Label
-> Seq AnnotInstr
-> A.Exp
-> ConvertM (Seq Block)
, contextConvertExp
:: Context -> ExpContext
-> A.Exp
-> ConvertM (Seq AnnotInstr)
, contextConvertCase
:: Context -> ExpContext
-> Label
-> Seq AnnotInstr
-> A.Exp
-> [A.Alt]
-> ConvertM (Seq Block)
}
-- | Holds the result of converting an alternative.
data AltResult
= AltDefault Label (Seq Block)
| AltCase Lit Label (Seq Block)
-- | Extend the kind environment of a context with a new binding.
extendKindEnv :: Bind A.Name -> Context -> Context
extendKindEnv b ctx
= ctx { contextKindEnv = Env.extend b (contextKindEnv ctx) }
-- | Extend the kind environment of a context with some new bindings.
extendsKindEnv :: [Bind A.Name] -> Context -> Context
extendsKindEnv bs ctx
= ctx { contextKindEnv = Env.extends bs (contextKindEnv ctx) }
-- | Extend the type environment of a context with a new binding.
extendTypeEnv :: Bind A.Name -> Context -> Context
extendTypeEnv b ctx
= ctx { contextTypeEnv = Env.extend b (contextTypeEnv ctx) }
-- | Extend the type environment of a context with some new bindings.
extendsTypeEnv :: [Bind A.Name] -> Context -> Context
extendsTypeEnv bs ctx
= ctx { contextTypeEnv = Env.extends bs (contextTypeEnv ctx) }
---------------------------------------------------------------------------------------------------
-- | What expression context we're doing this conversion in.
data ExpContext
-- | Conversion at the top-level of a function.
-- The expresison being converted must eventually pass control.
= ExpTop
-- | In a nested context, like in the right of a let-binding.
-- The expression should produce a value that we assign to this
-- variable, then jump to the provided label to continue evaluation.
| ExpNest ExpContext Var Label
-- | In a nested context where we need to assign the result
-- to the given variable and fall through.
| ExpAssign ExpContext Var
-- | Take any assignable variable from a `Context`.
takeVarOfContext :: ExpContext -> Maybe Var
takeVarOfContext context
= case context of
ExpTop -> Nothing
ExpNest _ var _ -> Just var
ExpAssign _ var -> Just var
-- | Take any assignable variable from a `Context`, but only if it has a non-void type.
-- In LLVM we can't assign to void variables.
takeNonVoidVarOfContext :: ExpContext -> Maybe Var
takeNonVoidVarOfContext context
= case takeVarOfContext context of
Just (Var _ TVoid) -> Nothing
mv -> mv