@@ -5,13 +5,14 @@ module Gibbon.Passes.FollowPtrs
55import qualified Data.Map as M
66-- import qualified Data.Set as S
77import qualified Data.List as L
8- -- import Data.Foldable ( foldrM )
8+ import Data.Foldable ( foldrM )
99import Data.Maybe ( fromJust )
1010
1111import Gibbon.Common
1212import Gibbon.Language
1313import Gibbon.L2.Syntax as L2
1414import Gibbon.DynFlags
15+ import Gibbon.L3.Syntax (E3Ext (AddCursor ))
1516
1617--------------------------------------------------------------------------------
1718
@@ -66,12 +67,44 @@ followPtrs (Prog ddefs fundefs mainExp) = do
6667 -- because bounds checking may have updated the value of the location.
6768 -- Note that we only need to update the non packed locations + the data constructor buffer.
6869 -- Other packed types will be updated by the function that traverses it.
70+ (new_out_locs, new_loc_bnds) <- foldrM (\ locvar (nl, bnds) -> case locvar of
71+ SoA dloc flocs -> do
72+ -- unpack all locations in the SoA location.
73+ let unpack_dcon = LetLocE (singleLocVar dloc) (GetDataConLocSoA locvar)
74+ let unpack_flds = map (\ ((dcon, idx), floc) -> do
75+ let flet = LetLocE floc (GetFieldLocSoA (dcon, idx) locvar)
76+ in flet
77+ ) flocs
78+ -- make a new name for this loc_var
79+ new_locvar <- freshCommonLoc " copy" locvar
80+ let new_don_loc = getDconLoc new_locvar
81+ -- The data con loc should be unpacked and updated by bounds check.
82+ -- from design of the compiler
83+ let new_don_let = LetLocE new_don_loc (AfterConstantLE 0 (singleLocVar dloc))
84+ let new_fld_locs = getAllFieldLocsSoA new_locvar
85+ new_fld_lets <- foldrM (\ ((dcon, idx), nfloc) flts -> do
86+ let ty = (lookupDataCon ddefs dcon) !! idx
87+ in case (ty) of
88+ PackedTy {} -> do
89+ let let_for_fld = LetLocE nfloc (GetFieldLocSoA (dcon, idx) locvar)
90+ in pure $ flts ++ [let_for_fld]
91+ _ -> do
92+ let let_for_fld = LetLocE nfloc (AfterConstantLE 0 (getFieldLoc (dcon, idx) locvar))
93+ in pure $ flts ++ [let_for_fld]
94+ ) [] new_fld_locs
95+ let new_soa_loc_let = LetLocE new_locvar (GenSoALoc new_don_loc new_fld_locs)
96+ return $ (nl ++ [new_locvar], bnds ++ [unpack_dcon] ++ unpack_flds ++ [new_don_let] ++ new_fld_lets ++ [new_soa_loc_let])
97+
98+ -- no need to update single location variables
99+ Single {} -> return $ (nl ++ [locvar], bnds)
100+ ) ([] , [] ) out_locs
69101
70102 let redir_dcon = fst $ fromJust $ L. find (isRedirectionTag . fst ) dataCons
71103 let redir_bod = (if isPrinterName funName then LetE (wc,[] ,ProdTy [] ,PrimAppE PrintSym [LitSymE (toVar " ->r " )]) else id ) $
72- LetE (callv,endofs,out_ty,AppE funName (in_locs ++ out_locs ) args) $
104+ LetE (callv,endofs,out_ty,AppE funName (in_locs ++ new_out_locs ) args) $
73105 Ext (RetE endofs callv)
74- let redir_br = (redir_dcon,[(indir_ptrv,(indir_ptrloc))],redir_bod)
106+ let redir_bod' = foldr (\ bnd bod -> Ext $ bnd bod) redir_bod new_loc_bnds
107+ let redir_br = (redir_dcon,[(indir_ptrv,(indir_ptrloc))],redir_bod')
75108 ----------------------------------------
76109 (pure (CaseE scrt (brs ++ [redir_br])))
77110 else do
0 commit comments