From 4c1f2a193002638c2c70afbac72297fc497ff835 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Thu, 6 Mar 2008 19:08:38 +0000 Subject: [PATCH] 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 --- backends/GenerateC.hs | 92 +++++-------- backends/GenerateCPPCSP.hs | 262 ++----------------------------------- pass/PassList.hs | 2 + 3 files changed, 48 insertions(+), 308 deletions(-) diff --git a/backends/GenerateC.hs b/backends/GenerateC.hs index 9def0b9..1649517 100644 --- a/backends/GenerateC.hs +++ b/backends/GenerateC.hs @@ -17,7 +17,7 @@ with this program. If not, see . -} -- | 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 "] - 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"]) + do call genDecl am t n + tell [", const int *"] + genName n + tell ["_sizes"] + _ -> call genDecl am t n --}}} --{{{ processes diff --git a/backends/GenerateCPPCSP.hs b/backends/GenerateCPPCSP.hs index de33d77..1eda25d 100644 --- a/backends/GenerateCPPCSP.hs +++ b/backends/GenerateCPPCSP.hs @@ -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 diff --git a/pass/PassList.hs b/pass/PassList.hs index 6e33cf1..fc9203a 100644 --- a/pass/PassList.hs +++ b/pass/PassList.hs @@ -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]