From b0faa0e3872e0c35e0f74a861f9ad564a4390128 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Thu, 16 Apr 2009 18:42:27 +0000 Subject: [PATCH] Fixed the sizes for mobile arrays of mobile arrays The pass was folding the two arrays together, then digging too far into the dimensions of the outer array, rather than looking at the dimensions of the inner array. --- backends/BackendPasses.hs | 46 ++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/backends/BackendPasses.hs b/backends/BackendPasses.hs index dd51730..118dc3f 100644 --- a/backends/BackendPasses.hs +++ b/backends/BackendPasses.hs @@ -245,51 +245,65 @@ sliceDrop m skip total -- The Variable returned will always be Just, but it makes use from findVarSizes -- easier findSizeForVar :: Meta -> Int -> A.Variable -> - PassM (Maybe A.Name, Maybe A.Variable, [A.Expression]) + PassM (Maybe (Maybe A.Name, Maybe A.Variable, [A.Expression])) findSizeForVar m skip v = do t <- astTypeOf v case stripMobile t of A.Array ds _ - -> do debug $ show (m, skip, ds) + | skip >= length ds -> + -- This can happen, for example, with a mobile array of mobile arrays. + -- In this case, we need to indicate to our caller that they must + -- the specific subscript (that they probably skipped over) to find + -- the size of that mobile array + return Nothing + | otherwise -> + do debug $ show (m, skip, ds) let es = drop skip [e | A.Dimension e <- ds] mn <- case partition (== A.UnknownDimension) ds of ([], ds) -> getSizes m v es _ -> return Nothing case mn of - Just n -> return (Just n, Just $ A.Variable m n, es) - _ -> return (Nothing, + Just n -> return $ Just (Just n, Just $ A.Variable m n, es) + _ -> return $ Just (Nothing, Just $ sliceDrop m skip (length ds) $ A.VariableSizes m v, [A.ExprVariable m $ A.SubscriptedVariable m (A.Subscript m A.NoCheck $ makeConstant m i) (A.VariableSizes m v) | i <- [skip .. (length ds - 1)]]) - _ -> diePC m $ formatCode "findSizeForVar for type % (for variable %)" t v + _ -> return Nothing where stripMobile (A.Mobile t) = stripMobile t +{- stripMobile (A.Array ds t) = case stripMobile t of A.Array ds' innerT -> A.Array (ds ++ ds') innerT t' -> A.Array ds t' +-} stripMobile t = t -- Gets the variable that holds the sizes of the given variable. The first parameter -- is the number of dimensions to skip. Assumes simplifySlices has already been -- run -findVarSizes :: Int -> A.Variable -> PassM (Maybe A.Name, Maybe A.Variable, [A.Expression]) +findVarSizes :: Int -> A.Variable -> PassM (Maybe (Maybe A.Name, Maybe A.Variable, [A.Expression])) findVarSizes skip v@(A.Variable m _) = findSizeForVar m skip v findVarSizes skip (A.DirectedVariable _ _ v) = findVarSizes skip v -- Fields are either constant or need a VariableSizes: findVarSizes skip v@(A.SubscriptedVariable m (A.SubscriptField {}) _) = findSizeForVar m skip v -- For a specific subscript, drop one extra dimension off the inner dimensions: -findVarSizes skip (A.SubscriptedVariable _ (A.Subscript {}) v) - = findVarSizes (skip + 1) v +findVarSizes skip wholeV@(A.SubscriptedVariable m (A.Subscript {}) v) + = do sizes <- findVarSizes (skip + 1) v + if isJust sizes + then return sizes + -- We went too far, and we may be an array of arrays, so try a different + -- approach: + else findSizeForVar m skip wholeV -- This covers all slicing: findVarSizes skip v@(A.SubscriptedVariable m (A.SubscriptFromFor _ _ from for) innerV) -- If we are skipping at least one dimension, we can ignore slicing: | skip > 0 = findVarSizes skip innerV | otherwise = do sizes <- findVarSizes 0 innerV case sizes of - (_, _, _:es) -> return (Nothing, Nothing, for : es) - (_, _, []) -> diePC m $ formatCode "Empty sizes for sliced array: %" innerV + Just (_, _, _:es) -> return $ Just (Nothing, Nothing, for : es) + _ -> diePC m $ formatCode "Empty sizes for sliced array: %" innerV -- the size of a dereference is the size of the mobile array: findVarSizes skip (A.DerefVariable _ v) = findVarSizes skip v -- Not sure this should ever happen, but no harm: @@ -299,7 +313,7 @@ findVarSizes skip (A.VariableSizes m v) dieP m "Told to drop (at least) one from size of VariableSizes!" let es = drop skip [makeConstant m (length ds)] mn <- getSizes m (A.VariableSizes m v) es - return (mn, fmap (A.Variable m) mn, es) + return $ Just (mn, fmap (A.Variable m) mn, es) type DeclSizeOps = (ExtOpMSP BaseOp) `ExtOpMP` A.Process @@ -389,14 +403,16 @@ declareSizesArray = occamOnlyPass "Declare array-size arrays" case sizeExpr of -- It was constant, and a new global declaration made, so we just -- need to return the name, and no specification - (Just sizeN, _, _) -> return (sizeN, Nothing) + Just (Just sizeN, _, _) -> return (sizeN, Nothing) -- We can use/slice a previous sizes item, so our abbreviation is -- quite simple: - (Nothing, Just sizeV, _) -> + Just (Nothing, Just sizeV, _) -> do t <- astTypeOf sizeV return (n_sizes, Just $ A.Is m A.ValAbbrev t (A.ActualVariable sizeV)) -- We have to declare a full array of sizes: - (Nothing, Nothing, es) -> return (n_sizes, Just $ makeSizeSpec m es) + Just (Nothing, Nothing, es) -> return (n_sizes, Just $ makeSizeSpec m es) + -- Error: + Nothing -> diePC m $ formatCode "Cannot work out sizes for %" abbrevV makeSizeSpec :: Meta -> [A.Expression] -> A.SpecType makeSizeSpec m es = A.Is m A.ValAbbrev t (A.ActualExpression e) @@ -479,7 +495,7 @@ declareSizesArray = occamOnlyPass "Declare array-size arrays" -- But even if all the dimensions are known, we must still add the sizes -- as a global thingy (provided it's not an external): | isNothing ext -> - do (Just n_sizes, _, _) <- findVarSizes 0 (A.Variable m n) + do Just (Just n_sizes, _, _) <- findVarSizes 0 (A.Variable m n) addSizes (A.nameName n) n_sizes (rest, moreNew) <- transformFormals ext m fs return (f : rest, moreNew)