aboutsummaryrefslogtreecommitdiff
path: root/CodeGen.hs
diff options
context:
space:
mode:
Diffstat (limited to 'CodeGen.hs')
-rw-r--r--CodeGen.hs82
1 files changed, 64 insertions, 18 deletions
diff --git a/CodeGen.hs b/CodeGen.hs
index 450f887..bcc49a0 100644
--- a/CodeGen.hs
+++ b/CodeGen.hs
@@ -75,11 +75,26 @@ codegen (IRProgram vars funcs) = do
codegenVar :: DVar -> Error String
-codegenVar (DVar TInt n (ELit (LInt i) (Just TInt))) = Right $ n ++ ": dq " ++ show i
-codegenVar (DVar (TArr TChar _) n (ELit (LStr s) _)) = Right $
- n ++ ":\n" ++
+codegenVar (DVar TInt n (ELit (LInt i) _)) = return $ n ++ ": dq " ++ show i
+codegenVar (DVar TChar n (ELit (LChar c) _)) = return $ n ++ ": db " ++ show (ord c)
+codegenVar (DVar (TArr TChar _) n (ELit (LStr s) _)) = return $
+ "$" ++ n ++ ":\n" ++
"\tdq " ++ show (length s + 1) ++ "\n" ++
"\tdb " ++ (intercalate ", " $ map show $ map ord s ++ [0])
+codegenVar (DVar t@(TStruct _) n e@(ELit (LStruct _) _)) =
+ (("$" ++ n ++ ":\n") ++) <$> genDataFor t e
+ where
+ genDataFor :: Type -> Expression -> Error String
+ genDataFor TInt (ELit (LInt i) _) = return $ "dq " ++ show i
+ genDataFor TChar (ELit (LChar c) _) = return $ "db " ++ show (ord c)
+ genDataFor (TStruct ms') (ELit (LStruct exprtups') _) =
+ liftM (intercalate "\n" . map ('\t' :) . concatMap lines) $
+ forM (zip ms' exprtups') $ \((typ, name), (name2, expr)) ->
+ if name /= name2
+ then Left $ "Invalid struct literal member order somewhere " ++
+ "in a global variable declaration"
+ else genDataFor typ expr
+ genDataFor _ _ = Left "Unsupported expression in struct literal in global variable declaration"
codegenVar _ = Left "Unsupported global variable declaration"
@@ -95,7 +110,7 @@ codegenFunc (IRFunc _ name al bbs sid) = do
aliascandidates = findAliasCandidates bbs :: [(Ref, Ref)]
- gpRegs = [R8, R9, R10, R11, R12, R13, R14, R15]
+ gpRegs = [R8, R9, R10, R11, R12, R13, R14, R15, RDI, RSI]
-- gpRegs = [R8]
allocation = regalloc lifespans gpRegs aliascandidates :: Map.Map Ref (Allocation Register)
@@ -255,8 +270,8 @@ codegenIns m (ILea d n)
codegenIns m (IStore d s) = do
sourcexref <- if X64.isXMem sm
then do
- addIns $ mkmov (XReg sz RBX) sm
- return $ XReg sz RBX
+ addIns $ mkmov (XReg sz RDX) sm
+ return $ XReg sz RDX
else return sm
destxref <- case dm of
XReg _ r -> return $ XMem sz (Just r) (0, RAX) Nothing 0
@@ -302,26 +317,57 @@ codegenIns m (IGet d s off)
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)
- addIns $ mkmov (XReg sz RBX) (mkxref s2 m)
- addIns $ IMULDA (xref $ XReg sz RBX)
- addIns $ mkmov (mkxref d m) (XReg sz RAX)
+codegenIns m (IAri AMul d s1 s2)
+ | X64.isXImm s1m && X64.isXImm s2m = undefined
+ | X64.isXImm s1m = codegenIns m (IAri AMul d s2 s1)
+ | otherwise = do
+ -- regmem dm, regmem s1m, regmemimm s2m
+ let sz = fromIntegral $ refSize d
+ if X64.isXImm s2m
+ then if X64.isXMem dm
+ then do -- mem dm, regmem s1m, imm s2m
+ addIns $ IMUL3 (xref $ XReg sz RAX) (xref s1m) (xref s2m)
+ addIns $ mkmov dm (XReg sz RAX)
+ else do -- reg dm, regmem s1m, imm s2m
+ addIns $ IMUL3 (xref dm) (xref s1m) (xref s2m)
+ else if X64.isXMem dm
+ then do -- mem dm, regmem s1m, regmem s2m
+ addIns $ mkmov (XReg sz RAX) s1m
+ addIns $ IMUL (xref $ XReg sz RAX) (xref s2m)
+ addIns $ mkmov dm (XReg sz RAX)
+ else if dm == s1m
+ then do -- reg dm = reg s1m, regmem s2m
+ addIns $ IMUL (xref dm) (xref s2m)
+ else do -- reg dm, regmem s1m, regmem s2m
+ addIns $ mkmov dm s1m
+ addIns $ IMUL (xref dm) (xref s2m)
+ where dm = mkxref d m
+ s1m = mkxref s1 m
+ s2m = mkxref s2 m
codegenIns m (IAri ADiv d s1 s2) = do
let sz = fromIntegral $ refSize d
addIns $ XOR (xref $ XReg 4 RDX) (xref $ XReg 4 RDX)
addIns $ mkmov (XReg sz RAX) (mkxref s1 m)
- addIns $ mkmov (XReg sz RBX) (mkxref s2 m)
- addIns $ IDIVDA (xref $ XReg sz RBX)
+ arg <- if X64.isXImm s2m
+ then do
+ addIns $ mkmov (XReg sz RBX) s2m
+ return (XReg sz RBX)
+ else return s2m
+ addIns $ IDIVDA (xref arg)
addIns $ mkmov (mkxref d m) (XReg sz RAX)
+ where s2m = mkxref s2 m
codegenIns m (IAri AMod d s1 s2) = do
let sz = fromIntegral $ refSize d
addIns $ XOR (xref $ XReg 4 RDX) (xref $ XReg 4 RDX)
addIns $ mkmov (XReg sz RAX) (mkxref s1 m)
- addIns $ mkmov (XReg sz RBX) (mkxref s2 m)
- addIns $ IDIVDA (xref $ XReg sz RBX)
+ arg <- if X64.isXImm s2m
+ then do
+ addIns $ mkmov (XReg sz RBX) s2m
+ return (XReg sz RBX)
+ else return s2m
+ addIns $ IDIVDA (xref arg)
addIns $ mkmov (mkxref d m) (XReg sz RDX)
+ where s2m = mkxref s2 m
codegenIns m (IAri at d s1 s2) = case arithTypeToCondCode at of
Just cc -> do
arg2 <- if X64.isXMem s1m && X64.isXMem s2m
@@ -349,8 +395,8 @@ codegenIns m (IAri at d s1 s2) = case arithTypeToCondCode at of
else return s2m'
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)
+ addIns $ mkmov (XReg (fromIntegral $ refSize s1') RDX) s1m'
+ addIns $ mkmov dm (XReg (fromIntegral $ refSize s1') RDX)
else do
addIns $ mkmov dm s1m'
addIns $ fromJust (arithTypeToIns at) dm arg2