Adjusted the C++ (a lot) and C (a little) backends to reflect array _sizes changes, and added the new array passes to the overall pass list

Now that I have begun moving all the _sizes stuff forward into proper compiler passes, much of the code for handling arrays in the backends is going to become redundant:

- The tockArrayView class should eventually disappear; now that _sizes are pulled forward, there's no advantage of having this extra class (compared to just doing C and C++ arrays in the same, C-based, style)
- The declaration and use of the _sizes array everywhere should go, now that it is inserted in an earlier pass

I haven't removed as much as I should from the C backend; I am wary to touch it when Adam is about to move it over to the new CIF anyway
This commit is contained in:
Neil Brown 2008-03-06 19:08:38 +00:00
parent a751531b4e
commit 4c1f2a1930
3 changed files with 48 additions and 308 deletions

View File

@ -17,7 +17,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
-}
-- | Generate C code from the mangled AST.
module GenerateC (cgenOps, cintroduceSpec, cPreReq, fget, genComma, genCPasses, generate, generateC, genLeftB, genMeta, genName, genRightB, GenOps(..), indexOfFreeDimensions, seqComma, withIf ) where
module GenerateC (cgenLiteralRepr, cgenOps, cgenSlice, cgenType, cintroduceSpec, cPreReq, fget, genComma, genCPasses, generate, generateC, genLeftB, genMeta, genName, genRightB, GenOps(..), indexOfFreeDimensions, seqComma, withIf ) where
import Data.Char
import Data.Generics
@ -1028,8 +1028,10 @@ cgenSlice v@(A.SubscriptedVariable _ _ (A.Variable _ on)) start count ds
genRightB
))
-- TODO remove this function altogether (and from the dictionary) in future
cgenArraySizeDecl :: Bool -> CGen () -> A.Name -> CGen ()
cgenArraySizeDecl isPtr size n
cgenArraySizeDecl isPtr size n = return ()
{-
= if isPtr
then do tell ["const int*"]
genName n
@ -1041,7 +1043,7 @@ cgenArraySizeDecl isPtr size n
tell ["_sizes[]="]
size
tell [";"]
-}
noSize :: A.Name -> CGen ()
noSize n = return ()
@ -1051,6 +1053,7 @@ cgenVariableAM v am
call genVariable v
-- | Generate the right-hand side of an abbreviation of a variable.
-- TODO the array _sizes code here is going to be redundant
abbrevVariable :: A.AbbrevMode -> A.Type -> A.Variable -> (CGen (), A.Name -> CGen ())
abbrevVariable am (A.Array _ _) v@(A.SubscriptedVariable _ (A.Subscript _ _) _)
= (tell ["&"] >> call genVariable v, genAASize v 0)
@ -1170,7 +1173,6 @@ cgenDeclaration (A.Array ds t) n True
tell ["int "]
genName n
tell ["_sizes[",show $ length ds,"];"]
cgenDeclaration A.Timer _ _ = return ()
cgenDeclaration t n _
= do call genType t
tell [" "]
@ -1405,7 +1407,30 @@ cgenActuals :: [A.Actual] -> CGen ()
cgenActuals as = prefixComma (map (call genActual) as)
cgenActual :: A.Actual -> CGen ()
cgenActual actual = seqComma $ realActuals actual
cgenActual actual
= case actual of
A.ActualExpression t e ->
case (t, e) of
(A.Array _ _, A.ExprVariable _ v) ->
do call genVariable v
tell [","]
call genVariable v
tell ["_sizes"]
_ -> call genExpression e
A.ActualVariable am t v ->
case t of
A.Array _ _ ->
do call genVariable v
tell [","]
call genVariable v
tell ["_sizes"]
_ -> fst $ abbrevVariable am t v
numCArgs :: [A.Actual] -> Int
numCArgs [] = 0
numCArgs (A.ActualVariable _ (A.Array _ _) _:fs) = 2 + numCArgs fs
numCArgs (A.ActualExpression (A.Array _ _) _:fs) = 2 + numCArgs fs
numCArgs (_:fs) = 1 + numCArgs fs
cgenFormals :: [A.Formal] -> CGen ()
cgenFormals fs = prefixComma (map (call genFormal) fs)
@ -1435,58 +1460,11 @@ realFormals :: A.Formal -> [(CGen (), CGen ())]
realFormals (A.Formal am t n)
= case t of
A.Array _ t' ->
[(mainType, mainName),
(tell ["const int *"], genName n >> tell ["_sizes"])]
_ -> [(mainType, mainName)]
where
mainType = cgenDeclType am t
mainName = genName n
-- | Generate a wrapper function for a PAR subprocess.
cgenProcWrapper :: A.Name -> CGen ()
cgenProcWrapper n
= do st <- specTypeOfName n
let fs = case st of A.Proc _ _ fs _ -> fs
let rfs = concatMap realFormals fs
tell ["static void "]
do call genDecl am t n
tell [", const int *"]
genName n
tell ["_wrapper (Workspace wptr) {\n"]
sequence_ [unpackParam num rf | (num, rf) <- zip [0..] rfs]
genName n
tell [" (wptr"]
prefixComma [n | (_, n) <- rfs]
tell [");\n"]
tell ["}\n"]
where
unpackParam :: Int -> (CGen (), CGen ()) -> CGen ()
unpackParam num (t, n)
= do t
tell [" "]
n
tell [" = ProcGetParam (wptr, " ++ show num ++ ", "]
t
tell [");\n"]
-- | Generate a ProcAlloc for a PAR subprocess, returning a nonce for the
-- workspace pointer and the name of the function to call.
cgenProcAlloc :: A.Name -> [A.Actual] -> CGen (String, CGen ())
cgenProcAlloc n as
= do let ras = concatMap realActuals as
ws <- makeNonce "workspace"
tell ["Workspace ", ws, " = ProcAlloc (wptr, ", show $ length ras, ", "]
genName n
tell ["_wrapper_stack_size);\n"]
sequence_ [do tell ["ProcParam (wptr, ", ws, ", ", show num, ", "]
ra
tell [");\n"]
| (num, ra) <- zip [(0 :: Int)..] ras]
return (ws, genName n >> tell ["_wrapper"])
tell ["_sizes"]
_ -> call genDecl am t n
--}}}
--{{{ processes

View File

@ -95,18 +95,13 @@ import Utils
-- Most of this is inherited directly from the C backend in the "GenerateC" module.
cppgenOps :: GenOps
cppgenOps = cgenOps {
declareArraySizes = cppdeclareArraySizes,
declareFree = cppdeclareFree,
declareInit = cppdeclareInit,
genActual = cppgenActual,
genActuals = cppgenActuals,
genAllocMobile = cppgenAllocMobile,
genAlt = cppgenAlt,
genArraySizesLiteral = cppgenArraySizesLiteral,
genArrayStoreName = cppgenArrayStoreName,
genArraySubscript = cppgenArraySubscript,
genClearMobile = cppgenClearMobile,
genDeclType = cppgenDeclType,
genDeclaration = cppgenDeclaration,
genDirectedVariable = cppgenDirectedVariable,
genForwardDeclaration = cppgenForwardDeclaration,
@ -118,8 +113,6 @@ cppgenOps = cgenOps {
genPar = cppgenPar,
genProcCall = cppgenProcCall,
genRetypeSizes = cppgenRetypeSizes,
genSizeSuffix = cppgenSizeSuffix,
genSlice = cppgenSlice,
genStop = cppgenStop,
genTimerRead = cppgenTimerRead,
genTimerWait = cppgenTimerWait,
@ -529,6 +522,7 @@ cppgenProcCall n as
--The vector has the suffix _actual, whereas the array-view is what is actually used in place of the array
--I think it may be possible to use boost::array instead of std::vector (which would be more efficient),
--but I will worry about that later
-- TODO this probably needs changing to reflect the new array system
cppgenDeclaration :: A.Type -> A.Name -> Bool -> CGen ()
cppgenDeclaration arrType@(A.Array ds t) n False
= do call genType t
@ -546,47 +540,12 @@ cppgenDeclaration arrType@(A.Array ds t) n False
call genFlatArraySize ds
tell [";"]
call declareArraySizes arrType n
cppgenDeclaration arrType@(A.Array ds t) n True
= do call genType t
tell [" "]
call genArrayStoreName n
call genFlatArraySize ds
tell [";"]
call genType arrType
tell [" "]
genName n;
tell [";"]
cppgenDeclaration t n _
= do call genType t
tell [" "]
genName n
tell [";"]
cppdeclareArraySizes :: A.Type -> A.Name -> CGen ()
cppdeclareArraySizes arrType@(A.Array ds _) n = do
tell ["const "]
call genType arrType
tell [" "]
genName n
tell ["="]
call genArraySizesLiteral n arrType
tell [";"]
cppgenArraySizesLiteral :: A.Name -> A.Type -> CGen ()
cppgenArraySizesLiteral n t@(A.Array ds _) =
do call genType t
tell ["("]
genName n
tell ["_actual,tockDims("]
seqComma dims
tell ["))"]
where
dims :: [CGen ()]
dims = [case d of
A.Dimension n -> tell [show n]
_ -> dieP (findMeta n) "unknown dimension in array type"
| d <- ds]
-- | Changed because we initialise channels and arrays differently in C++
cppdeclareInit :: Meta -> A.Type -> A.Variable -> Maybe A.Expression -> Maybe (CGen ())
cppdeclareInit m t@(A.Array ds t') var _
@ -609,18 +568,6 @@ cppdeclareInit m rt@(A.Record _) var _
| (n, t) <- fs]
where
initField :: A.Type -> A.Variable -> CGen ()
-- An array as a record field; we must initialise the sizes.
initField t@(A.Array ds ts) v
= do call genVariableUnchecked v
tell ["=tockArrayView<"]
call genType ts
tell [",",show (length ds),">("]
call genVariableUnchecked v
tell ["_actual,tockDims("]
infixComma [tell [show n] | (A.Dimension n) <- ds]
tell ["));"]
fdeclareInit <- fget declareInit
doMaybe $ fdeclareInit m t v Nothing
initField t v = do fdeclareInit <- fget declareInit
doMaybe $ fdeclareInit m t v Nothing
cppdeclareInit m _ v (Just e)
@ -642,30 +589,6 @@ cppremoveSpec (A.Specification m n (A.Declaration _ t _))
var = A.Variable m n
cppremoveSpec _ = return ()
cppgenArrayStoreName :: A.Name -> CGen()
cppgenArrayStoreName n = genName n >> tell ["_actual"]
--Changed from GenerateC because we don't need the extra code for array sizes
cppabbrevExpression :: A.AbbrevMode -> A.Type -> A.Expression -> CGen ()
cppabbrevExpression am t@(A.Array _ _) e
= case e of
A.ExprVariable _ v -> cppabbrevVariable am t v
A.Literal _ (A.Array ds _) r -> call genExpression e
_ -> bad
where
bad = call genMissing "array expression abbreviation"
cppabbrevExpression am _ e = call genExpression e
-- | Takes a list of dimensions and outputs a comma-seperated list of the numerical values
--Unknown dimensions have value 0 (which is treated specially by the tockArrayView class)
genDims:: [A.Dimension] -> CGen()
genDims dims = infixComma $ map genDim dims
where
genDim :: A.Dimension -> CGen()
genDim (A.Dimension n) = tell [show n]
genDim (A.UnknownDimension) = tell ["0"]
--Changed from GenerateC to add a name function (to allow us to use the same function for doing function parameters as constructor parameters)
--and also changed to use infixComma.
--Therefore these functions are not part of GenOps. They are called directly by cppgenForwardDeclaration and cppintroduceSpec.
@ -770,84 +693,9 @@ cppintroduceSpec (A.Specification _ n (A.Is _ am t v))
tell ["="]
rhs
tell [";"]
--Clause only changed to use C++ rather than C arrays:
cppintroduceSpec (A.Specification _ n (A.IsExpr _ am t e))
= do let rhs = cppabbrevExpression am t e
case (am, t, e) of
(A.ValAbbrev, A.Array _ ts, A.Literal _ (A.Array dims _) _) ->
-- For "VAL []T a IS [vs]:", we have to use [] rather than * in the
-- declaration, since you can't say "int *foo = {vs};" in C.
do tmp <- makeNonce "array_literal"
tell ["const "]
call genType ts
tell [" ",tmp, " [] = "]
rhs
tell [" ; "]
tell ["const tockArrayView< const "]
call genType ts
tell [" , ",show (length dims)," /**/>/**/ "]
genName n
tell ["(("]
call genType ts
tell [" *)",tmp,",tockDims("]
genDims dims
tell ["));\n"]
(A.ValAbbrev, A.Record _, A.Literal _ _ _) ->
-- Record literals are even trickier, because there's no way of
-- directly writing a struct literal in C that you can use -> on.
do tmp <- makeNonce "record_literal"
tell ["const "]
call genType t
tell [" ", tmp, " = "]
rhs
tell [";\n"]
call genDecl am t n
tell [" = &", tmp, ";\n"]
_ ->
do call genDecl am t n
tell [" = "]
rhs
tell [";\n"]
--Clause changed to handle array retyping
cppintroduceSpec (A.Specification _ n (A.Retypes m am t v))
= do origT <- typeOfVariable v
let rhs = cppabbrevVariable A.Abbrev origT v
call genDecl am t n
tell ["="]
case t of
(A.Array dims _) ->
--Arrays need to be handled differently because we need to feed the sizes in, not just perform a straight cast
do call genDeclType am t
tell ["(tockDims("]
genDims dims
tell ["),"]
rhs
tell [");"]
_ ->
-- For scalar types that are VAL abbreviations (e.g. VAL INT64),
-- we need to dereference the pointer that cppabbrevVariable gives us.
do let deref = case (am, t) of
(_, A.Chan A.DirUnknown _ _) -> False
(_, A.Record {}) -> False
(A.ValAbbrev, _) -> True
_ -> False
when deref $ tell ["*"]
tell ["("]
call genDeclType am t
when deref $ tell ["*"]
tell [")"]
case origT of
--We must be retyping from an array, but not to an array (so to a primitive type or something):
(A.Array _ _) -> tell ["("] >> rhs >> tell [".data())"]
_ -> rhs
tell [";"]
call genRetypeSizes m t n origT v
--For all other cases, use the C implementation:
cppintroduceSpec n = cintroduceSpec n
cppgenSizeSuffix :: String -> CGen ()
cppgenSizeSuffix dim = tell [".extent(", dim, ")"]
--}}}
@ -872,24 +720,11 @@ cppgetScalarType A.Timer = Just "csp::Time"
cppgetScalarType A.Time = Just "csp::Time"
cppgetScalarType _ = Nothing
-- | Generates an array type, giving the Blitz++ array the correct dimensions
cppgenArrayType :: Bool -> A.Type -> Int -> CGen ()
cppgenArrayType const (A.Array dims t) rank
= cppgenArrayType const t (rank + (max 1 (length dims)))
cppgenArrayType const t rank
= do tell ["tockArrayView<"]
when (const) (tell ["const "])
call genType t
case t of
A.Chan A.DirUnknown _ _ -> tell ["*"]
_ -> return ()
tell [",",show rank, ">/**/"]
-- | Changed from GenerateC to change the arrays and the channels
--Also changed to add counted arrays and user protocols
cppgenType :: A.Type -> CGen ()
cppgenType arr@(A.Array _ _)
= cppgenArrayType False arr 0
= cgenType arr
cppgenType (A.Record n) = genName n
cppgenType (A.Chan dir attr t)
= do let chanType = case dir of
@ -933,17 +768,17 @@ prefixUnderscore n = n { A.nameName = "_" ++ A.nameName n }
-- | Generate the right-hand side of an abbreviation of a variable.
--Changed from GenerateC because we no longer need the A.Name -> CGen() function returned that dealt with array sizes
--I also pass the type of the array through to cppgenSlice
-- Changed from GenerateC because we no longer need the A.Name -> CGen() function returned that dealt with array sizes
-- TODO I might be able to remove this once the C side has been changed too (now that _sizes arrays are declared elsewhere)
cppabbrevVariable :: A.AbbrevMode -> A.Type -> A.Variable -> CGen ()
cppabbrevVariable am (A.Array _ _) v@(A.SubscriptedVariable _ (A.Subscript _ _) _)
= call genVariable v
cppabbrevVariable am ty@(A.Array ds _) v@(A.SubscriptedVariable _ (A.SubscriptFromFor _ start count) _)
= fst (cppgenSlice v start count ds)
= fst (cgenSlice v start count ds)
cppabbrevVariable am ty@(A.Array ds _) v@(A.SubscriptedVariable m (A.SubscriptFrom _ start) v')
= fst (cppgenSlice v start (A.Dyadic m A.Minus (A.SizeExpr m (A.ExprVariable m v')) start) ds)
= fst (cgenSlice v start (A.Dyadic m A.Minus (A.SizeExpr m (A.ExprVariable m v')) start) ds)
cppabbrevVariable am ty@(A.Array ds _) v@(A.SubscriptedVariable m (A.SubscriptFor _ count) _)
= fst (cppgenSlice v (makeConstant m 0) count ds)
= fst (cgenSlice v (makeConstant m 0) count ds)
cppabbrevVariable am (A.Array _ _) v
= call genVariable v
cppabbrevVariable am (A.Chan {}) v
@ -954,66 +789,8 @@ cppabbrevVariable am t v
= call genVariableAM v am
-- | Use C++ array slices:
--TODO put index checking back:
cppgenSlice :: A.Variable -> A.Expression -> A.Expression -> [A.Dimension] -> (CGen (), A.Name -> CGen ())
cppgenSlice (A.SubscriptedVariable _ _ v) start count ds
-- We need to disable the index check here because we might be taking
-- element 0 of a 0-length array -- which is valid.
= (do call genVariableUnchecked v
tell [".sliceFromFor("]
genStart
tell [",occam_check_slice("]
genStart
tell [","]
call genExpression count
tell [","]
call genVariableUnchecked v
call genSizeSuffix "0"
tell [","]
genMeta (findMeta count)
tell ["))"]
, const (return ())
)
where
genStart = call genExpression start
-- | Changed from GenerateC to use multiple subscripting (e.g. [1][2][3]) rather than the combined indexing of the C method (e.g. [1*x*y+2*y+3])
cppgenArraySubscript :: Bool -> A.Variable -> [A.Expression] -> CGen ()
cppgenArraySubscript checkValid v es
= do t <- typeOfVariable v
let numDims = case t of A.Array ds _ -> length ds
sequence_ $ genPlainSub v es [0..(numDims - 1)]
--To index an actual element of an array we must use the .access() function
--Only needed when we have applied enough subscripts to get out an element:
when (numDims == (length es)) (tell [".access()"])
where
-- | Generate the individual offsets that need adding together to find the
-- right place in the array.
-- FIXME This is obviously not the best way to factor this, but I figure a
-- smart C compiler should be able to work it out...
--Subtly changed this function so that empty dimensions have blitz::Range::all() in the C++ version:
--TODO doc
genPlainSub :: A.Variable -> [A.Expression] -> [Int] -> [CGen ()]
genPlainSub _ _ [] = []
genPlainSub v [] (sub:subs) = (return ()) : (genPlainSub v [] subs)
genPlainSub v (e:es) (sub:subs)
= (tell ["["] >> genSub >> tell ["]"]) : genPlainSub v es subs
where
genSub
= if checkValid
then do tell ["occam_check_index("]
call genExpression e
tell [","]
call genVariable v
call genSizeSuffix (show sub)
tell [","]
genMeta (findMeta e)
tell [")"]
else call genExpression e
--}}}
-- TODO I think I can remove both these unfolded expression things now that
-- I've changed the arrays
-- | Changed to remove array size:
cppgenUnfoldedExpression :: A.Expression -> CGen ()
@ -1027,10 +804,6 @@ cppgenUnfoldedVariable :: Meta -> A.Variable -> CGen ()
cppgenUnfoldedVariable m var
= do t <- typeOfVariable var
case t of
A.Array ds _ ->
do genLeftB
unfoldArray ds var
genRightB
A.Record _ ->
do genLeftB
fs <- recordFields m t
@ -1072,21 +845,6 @@ cppgenIf m s
tell ["throw ",ifExc, "();}"]
--}}}
-- | Changed to make array VAL abbreviations have constant data:
cppgenDeclType :: A.AbbrevMode -> A.Type -> CGen ()
cppgenDeclType am t
= do case t of
A.Array _ _ -> cppgenArrayType (am == A.ValAbbrev) t 0
_ ->
do when (am == A.ValAbbrev) $ tell ["const "]
call genType t
case t of
A.Chan A.DirInput _ _ -> return ()
A.Chan A.DirOutput _ _ -> return ()
A.Record _ -> tell ["*const"]
_ -> when (am == A.Abbrev) $ tell ["*const"]
-- | Changed because C++CSP has channel-ends as concepts (whereas CCSP does not)
cppgenDirectedVariable :: CGen () -> A.Direction -> CGen ()
cppgenDirectedVariable v A.DirInput = tell ["(("] >> v >> tell [")->reader())"]
@ -1108,6 +866,8 @@ cppgenRetypeSizes m destT destN srcT srcV
call genStop m "size mismatch in RETYPES"
tell ["}"] in
case destT of
-- TODO we should be able to remove this check now that arrays have changed
-- An array -- figure out the genMissing dimension, if there is one.
A.Array destDS _ ->
case (indexOfFreeDimensions destDS) of

View File

@ -25,6 +25,7 @@ import Data.List
import qualified Data.Map as Map
import qualified Data.Set as Set
import BackendPasses
import Check
import CompState
import Errors
@ -50,6 +51,7 @@ commonPasses opts = concat $
, simplifyProcs
, unnest
, simplifyComms
, squashArrays
-- The occam frontend does a lot of work for us, so I represent that here:
,makePassesDep' ((== FrontendOccam) . csFrontend) [("Null occam pass", return, [],
Prop.agg_namesDone ++ [Prop.constantsFolded, Prop.expressionTypesChecked, Prop.inferredTypesRecorded, Prop.mainTagged, Prop.processTypesChecked]