Safe Haskell | None |
---|---|
Language | Haskell2010 |
Codegen.Codegen
Description
Translate SSM program to C compilation unit.
What is expected of the IR:
Well-formed: All primitive functions are applied to the right number of arguments.
Pure par expression: All par-expressions' operands are applications that have no side effects.
Defunctionalized: No lambdas; the only terms with an arrow type are variables or applications.
Name mangled: All variable identifiers are unique.
Synopsis
- todo :: HasCallStack => a
- nope :: HasCallStack => a
- newtype EscExp = EscExp String
- data GenFnState = GenFnState {}
- newtype GenFn a = GenFn (StateT GenFnState Pass a)
- runGenFn :: VarId -> [Binder Type] -> Expr Type -> TypegenInfo -> [(VarId, Type)] -> GenFn a -> Pass a
- getsTCon :: (TConInfo -> a) -> TConId -> GenFn a
- getsDCon :: (DConInfo -> a) -> DConId -> GenFn a
- nextCase :: GenFn Int
- getFresh :: GenFn Int
- addBinding :: Binder Type -> Exp -> GenFn ()
- addLocal :: VarId -> Type -> GenFn VarId
- withBindings :: [(Binder Type, Exp)] -> GenFn a -> GenFn a
- withNewLocal :: (VarId, Type) -> GenFn a -> GenFn a
- maxWait :: Int -> GenFn ()
- freshLabel :: GenFn CIdent
- genTmp :: Type -> GenFn Exp
- genParams :: [Binder Type] -> [(CIdent, Type)]
- genLocals :: [(VarId, Type)] -> [(CIdent, Type)]
- genTrigs :: Int -> [(CIdent, Type)]
- unit :: Exp
- undef :: Exp
- genProgram :: Program Type -> Pass [Definition]
- includes :: [Definition]
- genInitProgram :: VarId -> [Definition]
- genExtern :: (VarId, Type) -> Pass Definition
- genStruct :: GenFn Definition
- genEnter :: GenFn (Definition, Definition)
- genStaticClosure :: GenFn (Definition, Definition)
- genStep :: GenFn (Definition, Definition)
- genYield :: GenFn [BlockItem]
- genExpr :: Expr Type -> GenFn (Exp, [BlockItem])
- genPrim :: Primitive -> [Expr Type] -> Type -> GenFn (Exp, [BlockItem])
- genLiteral :: Literal -> Exp
- genLiteralRaw :: Literal -> Exp
- genPrimOp :: PrimOp -> [Expr Type] -> Type -> GenFn (Exp, [BlockItem])
- genBinop :: Expr Type -> Expr Type -> GenFn ((Exp, Exp), [BlockItem])
- genParArgs :: Int -> (Exp, Exp) -> [(Exp, Exp)]
- depthSub :: Int -> Exp
Documentation
todo :: HasCallStack => a Source #
Possible, but temporarily punted for the sake of expediency.
nope :: HasCallStack => a Source #
Impossible without a discussion about implementation strategy.
Hack to allow us to splice string literals into C AST
data GenFnState Source #
State maintained while compiling a top-level SSM function.
The information here is populated while generating the step function, so that should be computed first, before this information is used to generate the act struct and enter definitions.
Constructors
GenFnState | |
Fields
|
Instances
MonadState GenFnState GenFn Source # | |
Defined in Codegen.Codegen Methods get :: GenFn GenFnState # put :: GenFnState -> GenFn () # state :: (GenFnState -> (a, GenFnState)) -> GenFn a # |
Translation monad for procedures, with derived typeclass instances.
We declare GenFn
as a newtype so that we can implement MonadFail
for it,
allowing us to use monadic pattern matching.
Constructors
GenFn (StateT GenFnState Pass a) |
Instances
Monad GenFn Source # | |
Functor GenFn Source # | |
MonadFail GenFn Source # | |
Defined in Codegen.Codegen | |
Applicative GenFn Source # | |
MonadState GenFnState GenFn Source # | |
Defined in Codegen.Codegen Methods get :: GenFn GenFnState # put :: GenFnState -> GenFn () # state :: (GenFnState -> (a, GenFnState)) -> GenFn a # | |
MonadError Error GenFn Source # | |
Defined in Codegen.Codegen | |
MonadWriter [Warning] GenFn Source # | |
Arguments
:: VarId | Name of procedure |
-> [Binder Type] | Names and types of parameters to procedure |
-> Expr Type | Body of procedure |
-> TypegenInfo | Type information |
-> [(VarId, Type)] | Other global identifiers |
-> GenFn a | Translation monad to run |
-> Pass a | Pass on errors to caller |
Run a GenFn
computation on a procedure.
getsTCon :: (TConInfo -> a) -> TConId -> GenFn a Source #
Lookup some information associated with a type constructor.
getsDCon :: (DConInfo -> a) -> DConId -> GenFn a Source #
Lookup some information associated with a data constructor.
nextCase :: GenFn Int Source #
Read and increment the number of cases in a procedure, i.e., fnCases++
.
addLocal :: VarId -> Type -> GenFn VarId Source #
Register a new local variable, to be declared in activation record.
withBindings :: [(Binder Type, Exp)] -> GenFn a -> GenFn a Source #
Bind a variable to a C expression only while computing the given monad.
withNewLocal :: (VarId, Type) -> GenFn a -> GenFn a Source #
Register a local variable and bind its C expression during a monad.
maxWait :: Int -> GenFn () Source #
Register number of wait statements track of number of triggers needed.
freshLabel :: GenFn CIdent Source #
Generate a fresh label.
genTmp :: Type -> GenFn Exp Source #
Generate anonymous local variable in activation record for storage.
genParams :: [Binder Type] -> [(CIdent, Type)] Source #
Translate a list of SSM parameters to C parameters.
genLocals :: [(VarId, Type)] -> [(CIdent, Type)] Source #
Translate a list of SSM local declarations to C declarations.
genProgram :: Program Type -> Pass [Definition] Source #
Generate a C compilation from an SSM program.
Each top-level function in a program is turned into three components:
- a struct (the activation record);
- an initialization function (the enter function); and
- a step function, which corresponds to the actual procedure body.
Items 2 and 3 include both declarations and definitions.
genInitProgram :: VarId -> [Definition] Source #
Setup the entry point of the program.
genStruct :: GenFn Definition Source #
Generate struct definition for an SSM procedure.
This is where local variables, triggers, and parameter values are stored.
genEnter :: GenFn (Definition, Definition) Source #
Generate the enter function for an SSM procedure and its signature.
Its struct is allocated and initialized (partially; local variables' values are left uninitialized).
genStaticClosure :: GenFn (Definition, Definition) Source #
Generate static closure for top-level function
genStep :: GenFn (Definition, Definition) Source #
Generate the step function for an SSM procedure.
This function just defines the function definition and switch statement that
wraps the statements of the procedure. The heavy lifting is performed by
genExpr
.
genExpr :: Expr Type -> GenFn (Exp, [BlockItem]) Source #
Translate an SSM expression into a C expression and statements.
SSM IR is a side-effectful expression language, with two implications when translating to C:
- every expression has a value (even if it is an uninhabited type), so this must be reflected in C; and
- some of the side effects in SSM cannot be implemented in C using expressions alone.
These two implications roughly translate to the C.Exp
and [C.BlockItem]
in
genExpr
's return type. When we translate an SSM expression e
:
(val, stms) <- genExpr e
val
represents the C expression that corresponds to the value of e
upon
evaluation, while stms
represents the list of preceding statements that
compute val
.
A further consideration upon point 2 is that SSM expressions may yield control
at any point. Thus, the C expression returned by genExpr
must accommodate the
step function suspending and resuming. For instance, consider the following SSM
IR expression:
(let x = 3 in x) + (wait r; 6)
The x
in the let-binding in the left operand cannot just be a local variable
in the step function, because it would be "uninitialized" by the yield in the
right operand:
// let x = 3 in x // stms: int x = 3; // exp: x // (wait r; 6) // stms: ssm_sensitize(r); actg->pc = N; return; case N: ssm_desensitize(r); // exp: 6 // After the return, x is no longer initialized, so the following is // undefined behavior: x + 6
To ensure this is cannot happen, we conservatively declare x
as a local
variable in the activation record, so that its value is preserved between
yields, even if this is not usually necessary. We leave it to later compiler
passes to optimize this.
genPrim :: Primitive -> [Expr Type] -> Type -> GenFn (Exp, [BlockItem]) Source #
Generate code for SSM primitive; see genExpr
for extended discussion.
genLiteral :: Literal -> Exp Source #
Generate C value for SSM literal, marshalled.
genLiteralRaw :: Literal -> Exp Source #
Generate C value for SSM literal, unmarshalled.
genPrimOp :: PrimOp -> [Expr Type] -> Type -> GenFn (Exp, [BlockItem]) Source #
Generate C expression for SSM primitive operation.
genBinop :: Expr Type -> Expr Type -> GenFn ((Exp, Exp), [BlockItem]) Source #
Helper for sequencing across binary operations.
genParArgs :: Int -> (Exp, Exp) -> [(Exp, Exp)] Source #
Compute priority and depth arguments for a par fork of given width.