aboutsummaryrefslogtreecommitdiff
path: root/CodeGen.hs
diff options
context:
space:
mode:
Diffstat (limited to 'CodeGen.hs')
-rw-r--r--CodeGen.hs124
1 files changed, 95 insertions, 29 deletions
diff --git a/CodeGen.hs b/CodeGen.hs
index bf3e477..450f887 100644
--- a/CodeGen.hs
+++ b/CodeGen.hs
@@ -17,6 +17,7 @@ import Defs
import Intermediate
import qualified LifetimeAnalysis as LA
import RegAlloc
+import ReplaceRefs
import Utils
import X64 (Register(..), CondCode(..), XRef(..), Ins(..), xref)
import qualified X64 as X64
@@ -95,12 +96,16 @@ codegenFunc (IRFunc _ name al bbs sid) = do
aliascandidates = findAliasCandidates bbs :: [(Ref, Ref)]
gpRegs = [R8, R9, R10, R11, R12, R13, R14, R15]
+ -- gpRegs = [R8]
allocation = regalloc lifespans gpRegs aliascandidates :: Map.Map Ref (Allocation Register)
spillrefs = map fst $ filter (isAllocMem . snd) $ Map.toList allocation
(spilloffsets, spillsz) = initLast $ scanl (+) 0 $ map refSize spillrefs
spilloffsetmap = Map.fromList $ zip spillrefs spilloffsets
+ structrefs = filter isStructTemp $ findAllRefsBBList bbs
+ structspace = sum $ map refSize structrefs
+
usedregs = uniq $ sort $ catMaybes $ flip map (Map.toList allocation) $ \(_, a) -> case a of
AllocReg reg -> Just reg
AllocMem -> Nothing
@@ -110,31 +115,52 @@ codegenFunc (IRFunc _ name al bbs sid) = do
traceM $ "ALLOCATION: " ++ show allocation
let nsaves = length usedregs
- alignoff = if odd nsaves then 8 else 0
+ framesize' = 8 {- ret addr -} + 8 {- rbp -} + 8 * nsaves +
+ fromIntegral structspace + fromIntegral spillsz
+ alignoff = roundUp framesize' 16 - framesize'
+ framesize = framesize' + alignoff
allocationXref = flip Map.mapWithKey allocation $ \ref alloc -> case alloc of
AllocReg reg -> XReg (fromIntegral $ refSize ref) reg
AllocMem -> XMem (fromIntegral $ refSize ref)
(Just RSP) (0, RAX) Nothing
(fromIntegral $ spilloffsetmap ! ref)
- allocmap = foldl inserter allocationXref (zip al [0::Int ..])
+ allocmap' = fst $ foldl arginserter (allocationXref, 0) al
+ where
+ arginserter (m, off) (t, n) =
+ (Map.insert (Argument (sizeof t) n)
+ (XMem (fromIntegral $ sizeof t)
+ (Just RSP) (0, RAX) Nothing
+ (fromIntegral framesize + off))
+ m,
+ off + fromIntegral (sizeof t))
+
+ allocmap = fst $ foldl structinserter (allocmap', spillsz) structrefs
where
- inserter m ((t, n), i) =
- let offset = fromIntegral spillsz + alignoff + 8 * nsaves +
- 8 {- rbp -} + 8 {- ret addr -} + 8 * i
- in Map.insert (Argument (sizeof t) n)
- (XMem (fromIntegral $ sizeof t)
- (Just RSP) (0, RAX) Nothing
- (fromIntegral offset))
- m
+ structinserter (m, off) temp@(StructTemp sz _) =
+ (Map.insert temp
+ (XMem (fromIntegral sz)
+ (Just RSP) (0, RAX) Nothing
+ (fromIntegral off))
+ m,
+ off + sz)
+ structinserter _ _ = undefined
+
+ traceM $ "nsaves = " ++ show nsaves
+ traceM $ "structspace = " ++ show structspace
+ traceM $ "spillsz = " ++ show spillsz
+ traceM $ "framesize' = " ++ show framesize'
+ traceM $ "alignoff = " ++ show alignoff
+ traceM $ "framesize = " ++ show framesize
newLabel name
addIns $ PUSH (xref $ XReg 8 RBP)
addIns $ MOV (xref $ XReg 8 RBP) (xref $ XReg 8 RSP)
forM_ usedregs $ \reg -> addIns $ PUSH (xref $ XReg 8 reg)
- when (odd $ length usedregs) $ addIns $ SUB (xref $ XReg 8 RSP) (xref $ XImm 8)
- when (spillsz /= 0) $ addIns $ SUB (xref $ XReg 8 RSP) (xref $ XImm $ fromIntegral spillsz)
+ let stackspill = spillsz + structspace + fromIntegral alignoff
+ when (stackspill /= 0) $
+ addIns $ SUB (xref $ XReg 8 RSP) (xref $ XImm $ fromIntegral stackspill)
setRegsToRestore usedregs
- setSpillSize spillsz
+ setSpillSize stackspill
let ([startbb], rest) = partition (\(BB i _ _) -> i == sid) bbs
codegenBB allocmap startbb
@@ -192,6 +218,20 @@ mkmov a@(XMem _ _ _ _ _) b@(XImm v) | v < 2 ^ (32 :: Int) = MOV (xref a) (xref b
mkmov a b = CALL $ "Invalid mkmov: " ++ show a ++ "; " ++ show b
-- mkmov a b = error $ "Invalid mkmov: " ++ show a ++ "; " ++ show b
+emitmemcpy :: XRef -> XRef -> CGMonad ()
+emitmemcpy dst@(XMem sz _ _ _ _) src@(XMem sz2 _ _ _ _)
+ | sz /= sz2 = error $ "Inconsistent sizes in emitmemcpy: " ++ show dst ++ "; " ++ show src
+ | sz `elem` [1, 2, 4, 8] = do
+ addIns $ mkmov (XReg sz RAX) src
+ addIns $ mkmov dst (XReg sz RAX)
+ | sz > 8 = do
+ addIns $ mkmov (XReg 8 RAX) (X64.xrefSetSize 8 src)
+ addIns $ mkmov (X64.xrefSetSize 8 dst) (XReg 8 RAX)
+ emitmemcpy (X64.offsetXMem 8 $ X64.xrefSetSize (sz - 8) dst)
+ (X64.offsetXMem 8 $ X64.xrefSetSize (sz - 8) src)
+ | otherwise = error $ "Invalid size in emitmemcpy: " ++ show dst ++ "; " ++ show src
+emitmemcpy _ _ = undefined
+
mkcmp :: XRef -> XRef -> X64.Ins
mkcmp a b@(XImm _) = CMPi (xref a) (xref b)
mkcmp a b = CMP (xref a) (xref b)
@@ -244,6 +284,24 @@ codegenIns m (ILoad d s) = do
where dm = mkxref d m
sm = mkxref s m
sz = fromIntegral $ refSize d
+codegenIns m (ISet d off s)
+ | X64.isXMem sm = do
+ addIns $ mkmov (XReg sz RAX) sm
+ addIns $ mkmov dm (XReg sz RAX)
+ | otherwise = do
+ addIns $ mkmov dm sm
+ where dm = X64.xrefSetSize sz $ X64.offsetXMem (fromIntegral off) $ mkxref d m
+ sm = mkxref s m
+ sz = fromIntegral $ refSize s
+codegenIns m (IGet d s off)
+ | X64.isXMem dm = do
+ addIns $ mkmov (XReg sz RAX) sm
+ addIns $ mkmov dm (XReg sz RAX)
+ | otherwise = do
+ addIns $ mkmov dm sm
+ where dm = mkxref d m
+ sm = X64.xrefSetSize sz $ X64.offsetXMem (fromIntegral off) $ mkxref s m
+ sz = fromIntegral $ refSize d
codegenIns m (IAri AMul d s1 s2) = do
let sz = fromIntegral $ refSize d
addIns $ mkmov (XReg sz RAX) (mkxref s1 m)
@@ -275,7 +333,7 @@ codegenIns m (IAri at d s1 s2) = case arithTypeToCondCode at of
addIns $ SETCC cc (xref $ X64.xrefSetSize 1 dm)
addIns $ AND (xref $ X64.xrefSetSize 4 dm) (xref $ XImm 0xff)
Nothing -> do
- (_, s1m', s2', s2m') <-
+ (s1', s1m', s2', s2m') <-
if dm == s2m
then if dm == s1m
then return (s1, s1m, s2, s2m)
@@ -289,27 +347,35 @@ codegenIns m (IAri at d s1 s2) = case arithTypeToCondCode at of
addIns $ mkmov (XReg (fromIntegral $ refSize s2') RAX) s2m'
return $ XReg (fromIntegral $ refSize s2') RAX
else return s2m'
- when (dm /= s1m') $ addIns $ mkmov dm s1m'
+ when (dm /= s1m') $ if X64.isXMem dm && X64.isXMem s1m'
+ then do
+ addIns $ mkmov (XReg (fromIntegral $ refSize s1') RBX) s1m'
+ addIns $ mkmov dm (XReg (fromIntegral $ refSize s1') RBX)
+ else do
+ addIns $ mkmov dm s1m'
addIns $ fromJust (arithTypeToIns at) dm arg2
where dm = mkxref d m
s1m = mkxref s1 m
s2m = mkxref s2 m
codegenIns m (ICall n rs) = do
- when (odd $ length rs) $ addIns $ SUB (xref $ XReg 8 RSP) (xref $ XImm 8)
- forM_ (zip (reverse rs) [1::Int ..]) $ \(r, i) ->
+ let sizes = map (flip roundUp 8 . refSize) rs
+ offsets = init $ scanl (+) 0 $ reverse sizes
+ totalsize = sum sizes
+ alignment = roundUp totalsize 16 - totalsize
+ forM_ (zip rs offsets) $ \(r, off) ->
let sz = fromIntegral $ refSize r
- src = (mkxref r m)
- dst = (XMem sz (Just RSP) (0, RAX) Nothing (fromIntegral $ (-8) * i))
- in if X64.isXMem (mkxref r m)
+ src = mkxref r m
+ dst = XMem sz (Just RSP) (0, RAX) Nothing (fromIntegral $ off - alignment - totalsize)
+ in if X64.isXMem src
then do
- addIns $ mkmov (XReg sz RAX) src
- addIns $ mkmov dst (XReg sz RAX)
- else do
- addIns $ mkmov dst src
- when (length rs > 0) $ addIns $ SUB (xref $ XReg 8 RSP) (xref $ XImm (fromIntegral $ 8 * length rs))
+ traceM $ "call stuff with dst = " ++ show dst ++ ", src = " ++ show src
+ emitmemcpy dst src
+ else addIns $ mkmov dst src
+ when (alignment /= 0) $ addIns $ SUB (xref $ XReg 8 RSP) (xref $ XImm $ fromIntegral alignment)
+ when (length rs > 0) $ addIns $ SUB (xref $ XReg 8 RSP) (xref $ XImm $ fromIntegral totalsize)
addIns $ CALL n
- when (length rs > 0) $ addIns $ ADD (xref $ XReg 8 RSP) (xref $ XImm (fromIntegral $ 8 * length rs))
- when (odd $ length rs) $ addIns $ ADD (xref $ XReg 8 RSP) (xref $ XImm 8)
+ when (length rs > 0) $ addIns $ ADD (xref $ XReg 8 RSP) (xref $ XImm $ fromIntegral totalsize)
+ when (alignment /= 0) $ addIns $ ADD (xref $ XReg 8 RSP) (xref $ XImm $ fromIntegral alignment)
codegenIns m (ICallr d n rs) = do
codegenIns m (ICall n rs)
addIns $ mkmov (mkxref d m) (XReg (fromIntegral $ refSize d) RAX)
@@ -386,7 +452,6 @@ codegenTerm _ IRet = do
spillsz <- gets spillSize
when (spillsz /= 0) $ addIns $ ADD (xref $ XReg 8 RSP) (xref $ XImm $ fromIntegral spillsz)
usedregs <- gets regsToRestore
- when (odd $ length usedregs) $ addIns $ ADD (xref $ XReg 8 RSP) (xref $ XImm 8)
forM_ (reverse usedregs) $ \reg -> addIns $ POP (xref $ XReg 8 reg)
addIns $ mkmov (XReg 8 RSP) (XReg 8 RBP)
addIns $ POP (xref $ XReg 8 RBP)
@@ -396,7 +461,6 @@ codegenTerm m (IRetr r) = do
spillsz <- gets spillSize
when (spillsz /= 0) $ addIns $ ADD (xref $ XReg 8 RSP) (xref $ XImm $ fromIntegral spillsz)
usedregs <- gets regsToRestore
- when (odd $ length usedregs) $ addIns $ ADD (xref $ XReg 8 RSP) (xref $ XImm 8)
forM_ (reverse usedregs) $ \reg -> addIns $ POP (xref $ XReg 8 reg)
addIns $ mkmov (XReg 8 RSP) (XReg 8 RBP)
addIns $ POP (xref $ XReg 8 RBP)
@@ -417,6 +481,8 @@ collectTempRefs bbs =
listRefsIns (ILea a _) = [[LA.Write a]]
listRefsIns (IStore a b) = [[LA.Read a, LA.Read b]]
listRefsIns (ILoad a b) = [[LA.Read b], [LA.Write a]]
+ listRefsIns (ISet a _ b) = [[LA.Read b, LA.Write a]]
+ listRefsIns (IGet a b _) = [[LA.Read b, LA.Write a]]
listRefsIns (IAri at a b c)
-- if not commutative, we don't want to have to xchg the operands
| isCommutative at = [[LA.Read b, LA.Read c], [LA.Write a]]