copilot-c99 3.17 → 3.18
raw patch · 5 files changed
+98/−49 lines, 5 filesdep ~copilot-coredep ~language-c99-simplePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: copilot-core, language-c99-simple
API changes (from Hackage documentation)
Files
- CHANGELOG +7/−0
- copilot-c99.cabal +3/−3
- src/Copilot/Compile/C99/CodeGen.hs +40/−33
- src/Copilot/Compile/C99/Compile.hs +15/−4
- tests/Test/Copilot/Compile/C99.hs +33/−9
CHANGELOG view
@@ -1,3 +1,10 @@+2024-01-07+ * Version bump (3.18). (#487)+ * Change return type of main generated for tests. (#468)+ * Print constants in tests using portable suffixes. (#471).+ * Pass output arrays as arguments to trigger argument functions. (#431)+ * Compliance with MISRA C 2023 / MISRA C 2012. (#472)+ 2023-11-07 * Version bump (3.17). (#466) * Replace uses of deprecated functions. (#457)
copilot-c99.cabal view
@@ -1,6 +1,6 @@ cabal-version : >= 1.10 name : copilot-c99-version : 3.17+version : 3.18 synopsis : A compiler for Copilot targeting C99. description : This package is a back-end from Copilot to C.@@ -45,9 +45,9 @@ , mtl >= 2.2 && < 2.4 , pretty >= 1.1 && < 1.2 - , copilot-core >= 3.17 && < 3.18+ , copilot-core >= 3.18 && < 3.19 , language-c99 >= 0.2.0 && < 0.3- , language-c99-simple >= 0.2.2 && < 0.3+ , language-c99-simple >= 0.3 && < 0.4 exposed-modules : Copilot.Compile.C99
src/Copilot/Compile/C99/CodeGen.hs view
@@ -100,11 +100,18 @@ -- | Define an accessor functions for the ring buffer associated with a stream. mkAccessDecln :: Id -> Type a -> [a] -> C.FunDef-mkAccessDecln sId ty xs = C.FunDef cTy name params [] [C.Return (Just expr)]+mkAccessDecln sId ty xs =+ C.FunDef static cTy name params [] [C.Return (Just expr)] where+ static = Just C.Static cTy = C.decay $ transType ty name = streamAccessorName sId- buffLength = C.LitInt $ fromIntegral $ length xs++ -- We cast the buffer length to a size_t to make sure that there are no+ -- implicit conversions. This is a requirement for compliance with MISRA C+ -- (Rule 10.4).+ buffLength = C.Cast sizeT $ C.LitInt $ fromIntegral $ length xs+ sizeT = C.TypeName $ C.TypeSpec $ C.TypedefName "size_t" params = [C.Param (C.TypeSpec $ C.TypedefName "size_t") "x"] index = (C.Ident (indexName sId) C..+ C.Ident "x") C..% buffLength expr = C.Index (C.Ident (streamName sId)) index@@ -113,16 +120,19 @@ -- | Write a generator function for a stream. mkGenFun :: String -> Expr a -> Type a -> C.FunDef-mkGenFun name expr ty = C.FunDef cTy name [] cVars [C.Return $ Just cExpr]+mkGenFun name expr ty =+ C.FunDef static cTy name [] cVars [C.Return $ Just cExpr] where+ static = Just C.Static cTy = C.decay $ transType ty (cExpr, cVars) = runState (transExpr expr) mempty -- | Write a generator function for a stream that returns an array. mkGenFunArray :: String -> String -> Expr a -> Type a -> C.FunDef mkGenFunArray name nameArg expr ty@(Array _) =- C.FunDef funType name [ outputParam ] varDecls stmts+ C.FunDef static funType name [ outputParam ] varDecls stmts where+ static = Just C.Static funType = C.TypeSpec C.Void -- The output value is an array@@ -145,7 +155,7 @@ -- | Define the step function that updates all streams. mkStep :: CSettings -> [Stream] -> [Trigger] -> [External] -> C.FunDef mkStep cSettings streams triggers exts =- C.FunDef void (cSettingsStepFunctionName cSettings) [] declns stmts+ C.FunDef Nothing void (cSettingsStepFunctionName cSettings) [] declns stmts where void = C.TypeSpec C.Void @@ -163,6 +173,16 @@ (triggerDeclns, triggerStmts) = unzip $ map mkTriggerCheck triggers + -- Update the value of a variable with the result of calling a function that+ -- generates the next value in a stream expression. If the type of the+ -- variable is an array, then we cannot perform a direct C assignment, so+ -- we instead pass the variable as an output array to the function.+ updateVar :: C.Ident -> C.Ident -> Type a -> C.Expr+ updateVar varName genName (Array _) =+ C.Funcall (C.Ident genName) [C.Ident varName]+ updateVar varName genName _ =+ C.AssignOp C.Assign (C.Ident varName) (C.Funcall (C.Ident genName) [])+ -- Write code to update global stream buffers and index. mkUpdateGlobals :: Stream -> (C.Decln, C.Stmt, C.Stmt, C.Stmt) mkUpdateGlobals (Stream sId buff _expr ty) =@@ -170,10 +190,7 @@ where tmpDecln = C.VarDecln Nothing cTy tmpVar Nothing - tmpAssign = case ty of- Array _ -> C.Expr $ C.Funcall (C.Ident $ generatorName sId)- [ C.Ident tmpVar ]- _ -> C.Expr $ C.Ident tmpVar C..= val+ tmpAssign = C.Expr $ updateVar tmpVar (generatorName sId) ty bufferUpdate = case ty of Array _ -> C.Expr $ memcpy dest (C.Ident tmpVar) size@@ -187,13 +204,16 @@ indexUpdate = C.Expr $ indexVar C..= (incIndex C..% buffLength) where- buffLength = C.LitInt $ fromIntegral $ length buff- incIndex = indexVar C..+ C.LitInt 1+ -- We cast the buffer length and the literal one to a size_t to+ -- make sure that there are no implicit conversions. This is a+ -- requirement for compliance with MISRA C (Rule 10.4).+ buffLength = C.Cast sizeT $ C.LitInt $ fromIntegral $ length buff+ incIndex = indexVar C..+ C.Cast sizeT (C.LitInt 1)+ sizeT = C.TypeName $ C.TypeSpec $ C.TypedefName "size_t" tmpVar = streamName sId ++ "_tmp" buffVar = C.Ident $ streamName sId indexVar = C.Ident $ indexName sId- val = C.Funcall (C.Ident $ generatorName sId) [] cTy = transType ty -- Make code that copies an external variable to its local one.@@ -250,22 +270,8 @@ aTmpDeclns = zipWith declare args aTempNames where declare :: UExpr -> C.Ident -> C.Decln- declare arg tmpVar =- C.VarDecln Nothing (tempType arg) tmpVar Nothing-- -- Type of the temporary variable used to store values of the type- -- of a given expression.- tempType :: UExpr -> C.Type- tempType (UExpr { uExprType = ty }) =- case ty of- -- If a temporary variable is being used to store an array,- -- declare the type of the temporary variable as a pointer, not- -- an array. The problem with declaring it as an array is that- -- the `arg` function will return a pointer, not an array, and- -- C doesn't make it easy to cast directly from an array to a- -- pointer.- Array ty' -> C.Ptr $ transType ty'- _ -> transType ty+ declare (UExpr { uExprType = ty }) tmpVar =+ C.VarDecln Nothing (transType ty) tmpVar Nothing triggerCheckStmt :: C.Stmt triggerCheckStmt = C.If guard' fireTrigger@@ -283,13 +289,14 @@ where -- List of assignments of values of temporary variables. argAssigns :: [C.Expr]- argAssigns = zipWith assign aTempNames args'+ argAssigns = zipWith3 assign aTempNames aArgNames args - assign :: C.Ident -> C.Expr -> C.Expr- assign aTempName = C.AssignOp C.Assign (C.Ident aTempName)+ assign :: C.Ident -> C.Ident -> UExpr -> C.Expr+ assign aTempName aArgName (UExpr { uExprType = ty }) =+ updateVar aTempName aArgName ty - args' = take (length args) (map argCall (argNames name))- argCall name' = C.Funcall (C.Ident name') []+ aArgNames :: [C.Ident]+ aArgNames = take (length args) (argNames name) -- Build an expression to pass a temporary variable as argument -- to a trigger handler.
src/Copilot/Compile/C99/Compile.hs view
@@ -119,9 +119,8 @@ accessDecln (Stream sId buff _ ty) = mkAccessDecln sId ty buff streamGen :: Stream -> C.FunDef- streamGen (Stream sId _ expr ty@(Array _)) =- mkGenFunArray (generatorName sId) (generatorOutputArgName sId) expr ty- streamGen (Stream sId _ expr ty) = mkGenFun (generatorName sId) expr ty+ streamGen (Stream sId _ expr ty) =+ exprGen (generatorName sId) (generatorOutputArgName sId) expr ty triggerGen :: Trigger -> [C.FunDef] triggerGen (Trigger name guard args) = guardDef : argDefs@@ -130,7 +129,19 @@ argDefs = zipWith argGen (argNames name) args argGen :: String -> UExpr -> C.FunDef- argGen argName (UExpr ty expr) = mkGenFun argName expr ty+ argGen argName (UExpr ty expr) =+ exprGen argName (argName ++ "_output") expr ty++ -- Create a function that calculates the current value generated by an+ -- expression `expr` of type `ty`. The generator treats arrays+ -- specially, and the function takes an output array as a parameter.+ -- The second identifier `outputArrName` is not used if `expr` is not an+ -- array.+ exprGen :: C.Ident -> C.Ident -> Expr a -> Type a -> C.FunDef+ exprGen funName outputArrName expr ty@(Array _) =+ mkGenFunArray funName outputArrName expr ty+ exprGen funName _ expr ty =+ mkGenFun funName expr ty -- | Generate the .h file from a 'Spec'. compileH :: CSettings -> Spec -> C.TransUnit
tests/Test/Copilot/Compile/C99.hs view
@@ -157,7 +157,7 @@ , "void nop () {" , "}" , ""- , "void main () {"+ , "int main () {" , " step();" , "}" ]@@ -886,28 +886,52 @@ cshow :: s -> String instance CShow Int8 where- cshow = show+ -- Use a macro to ensure that any necessary suffixes are added to the number.+ -- We choose this macro instead of specifically adding a suffix for reasons+ -- of portability.+ cshow x = "INT8_C(" ++ show x ++ ")" instance CShow Int16 where- cshow = show+ -- Use a macro to ensure that any necessary suffixes are added to the number.+ -- We choose this macro instead of specifically adding a suffix for reasons+ -- of portability.+ cshow x = "INT16_C(" ++ show x ++ ")" instance CShow Int32 where- cshow = show+ -- Use a macro to ensure that any necessary suffixes are added to the number.+ -- We choose this macro instead of specifically adding a suffix for reasons+ -- of portability.+ cshow x = "INT32_C(" ++ show x ++ ")" instance CShow Int64 where- cshow = show+ -- Use a macro to ensure that any necessary suffixes are added to the number.+ -- We choose this macro instead of specifically adding a suffix for reasons+ -- of portability.+ cshow x = "INT64_C(" ++ show x ++ ")" instance CShow Word8 where- cshow = show+ -- Use a macro to ensure that any necessary suffixes are added to the number.+ -- We choose this macro instead of specifically adding a suffix for reasons+ -- of portability.+ cshow x = "UINT8_C(" ++ show x ++ ")" instance CShow Word16 where- cshow = show+ -- Use a macro to ensure that any necessary suffixes are added to the number.+ -- We choose this macro instead of specifically adding a suffix for reasons+ -- of portability.+ cshow x = "UINT16_C(" ++ show x ++ ")" instance CShow Word32 where- cshow = show+ -- Use a macro to ensure that any necessary suffixes are added to the number.+ -- We choose this macro instead of specifically adding a suffix for reasons+ -- of portability.+ cshow x = "UINT32_C(" ++ show x ++ ")" instance CShow Word64 where- cshow = show+ -- Use a macro to ensure that any necessary suffixes are added to the number.+ -- We choose this macro instead of specifically adding a suffix for reasons+ -- of portability.+ cshow x = "UINT64_C(" ++ show x ++ ")" instance CShow Float where cshow = show