From 2a54765a590e1d393442262002885adcbfe156cd Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Fri, 1 Sep 2017 23:09:41 +0200 Subject: Global structs, better imul/idiv --- AST.hs | 1 + CodeGen.hs | 82 +++++++++++++++++++++++++++++++++++++++++++++++-------------- X64.hs | 10 ++++---- struct.lang | 4 +++ 4 files changed, 74 insertions(+), 23 deletions(-) diff --git a/AST.hs b/AST.hs index ccad05d..7a76208 100644 --- a/AST.hs +++ b/AST.hs @@ -42,6 +42,7 @@ data Statement data AsExpression = AEVar Name (Maybe Type) | AESubscript AsExpression Expression (Maybe Type) + -- | AESet deriving (Show, Eq) data Expression 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 diff --git a/X64.hs b/X64.hs index 0cbf4fc..c2cbf81 100644 --- a/X64.hs +++ b/X64.hs @@ -203,7 +203,7 @@ stringify_only_xmem_brackets (XMem _ mr pair lab off) = goR1 (Just r) = Just $ stringify (XReg 8 r) goPair (0, _) = Nothing goPair (mult, r) = Just $ show mult ++ "*" ++ stringify (XReg 8 r) - goLab = id + goLab = fmap ('$' :) goOff o | o > 0 = '+' : show o | o < 0 = show o | otherwise = "" @@ -259,11 +259,11 @@ instance Stringifiable Ins where stringify (CMP a b) = "cmp " ++ stringify a ++ ", " ++ stringify b stringify (CMPi a b) = "cmp " ++ stringify a ++ ", " ++ stringify b stringify (SETCC cc a) = "set" ++ stringify cc ++ " " ++ stringify a - stringify (CALL a) = "call " ++ a + stringify (CALL a) = "call $" ++ a stringify (PUSH a) = "push " ++ stringify a stringify (POP a) = "pop " ++ stringify a - stringify (JMP s) = "jmp " ++ s - stringify (JCC cc s) = "j" ++ stringify cc ++ " " ++ s + stringify (JMP s) = "jmp $" ++ s + stringify (JCC cc s) = "j" ++ stringify cc ++ " $" ++ s stringify RET = "ret" stringify INT3 = "int3" @@ -271,7 +271,7 @@ instance Stringifiable Asm where stringify (Asm funcs) = intercalate "\n" $ map goF funcs where goF :: (String, [Ins]) -> String - goF (name, inss) = name ++ ":\n" ++ unlines (map (('\t' :) . stringify) inss) + goF (name, inss) = "$" ++ name ++ ":\n" ++ unlines (map (('\t' :) . stringify) inss) xrefGetSize :: XRef -> Int xrefGetSize (XReg s _) = s diff --git a/struct.lang b/struct.lang index 3297939..5bd38c4 100644 --- a/struct.lang +++ b/struct.lang @@ -3,12 +3,16 @@ type S := struct { char y; }; +S global := {x = 1, y = '!'}; + func f(int iets1, S s, int iets2) { putint(s.x); putc(s.y); putc('\n'); putint(iets1); putc(' '); putint(iets2); putc('\n'); } func int main() { + // global.x = 3 * global.x + int(global.y); + putint(global.x + 1); putc(global.y); putc('\n'); int a := getc(); int b := getc(); getc(); // newline -- cgit v1.2.3-70-g09d2