kempe 0.2.0.4 → 0.2.0.5
raw patch · 23 files changed
+206/−118 lines, 23 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +7/−0
- golden/Golden.hs +29/−0
- golden/Harness.hs +72/−0
- kempe.cabal +3/−2
- lib/either.kmp +8/−0
- lib/maybe.kmp +8/−0
- src/Kempe/Asm/Arm/ControlFlow.hs +6/−0
- src/Kempe/Check/Lint.hs +2/−0
- src/Kempe/IR.hs +4/−1
- src/Kempe/IR/Opt.hs +10/−3
- src/Kempe/TyAssign.hs +1/−1
- test/Golden.hs +0/−28
- test/Harness.hs +0/−72
- test/Type.hs +1/−0
- test/data/badCodegen.kmp +15/−0
- test/data/diamond/a.kmp +7/−0
- test/data/diamond/b.kmp +2/−0
- test/data/diamond/c.kmp +4/−0
- test/data/diamond/d.kmp +2/−0
- test/data/type.kmp +4/−0
- test/golden/gaussian.ir +7/−11
- test/golden/id.out +3/−0
- test/harness/id.c +11/−0
CHANGELOG.md view
@@ -1,5 +1,12 @@ # kempe +## 0.2.0.5++ * Fix bug in arm control-flow analysis+ * Fix bugs in IR optimization pass+ * Improve IR optimization+ * Add `fromMaybe` and `fromRight` functions+ ## 0.2.0.4 * Kind-check external function declarations
+ golden/Golden.hs view
@@ -0,0 +1,29 @@+module Main (main) where++import Data.Tuple.Extra (uncurry3)+import Harness+import System.Info (arch)+import Test.Tasty++main :: IO ()+main = defaultMain $+ testGroup "Golden output tests" $+ fmap (uncurry3 goldenOutput) allGoldens ++ crossTests++-- These are redundant on arm+crossTests :: [TestTree]+crossTests = case arch of+ "x86_64" -> fmap (uncurry3 crossGolden) allGoldens+ "aarch64" -> []+ _ -> error "Test suite must be run on x86_64 or aarch64"++allGoldens :: [(FilePath, FilePath, FilePath)]+allGoldens =+ [ ("examples/factorial.kmp", "test/harness/factorial.c", "test/golden/factorial.out")+ , ("test/examples/splitmix.kmp", "test/harness/splitmix.c", "test/golden/splitmix.out")+ , ("lib/numbertheory.kmp", "test/harness/numbertheory.c", "test/golden/numbertheory.out")+ , ("test/examples/hamming.kmp", "test/harness/hamming.c", "test/golden/hamming.out")+ , ("test/examples/bool.kmp", "test/harness/bool.c", "test/golden/bool.out")+ , ("test/examples/const.kmp", "test/harness/const.c", "test/golden/const.out")+ , ("test/data/badCodegen.kmp", "test/harness/id.c", "test/golden/id.out")+ ]
+ golden/Harness.hs view
@@ -0,0 +1,72 @@+module Harness ( goldenOutput+ , crossGolden+ ) where++import qualified Data.ByteString.Lazy as BSL+import qualified Data.ByteString.Lazy.Char8 as ASCII+import Data.Functor (void)+import Kempe.File+import System.FilePath ((</>))+import System.IO.Temp+import System.Info (arch)+import System.Process (CreateProcess (env, std_err), StdStream (Inherit), proc, readCreateProcess)+import Test.Tasty+import Test.Tasty.Golden (goldenVsString)+import Test.Tasty.HUnit (assertBool, testCase)++data CC = CC+ | ArmCC++instance Show CC where+ show CC = "cc"+ show ArmCC = "aarch64-linux-gnu-gcc"++runGcc :: CC+ -> [FilePath]+ -> FilePath+ -> IO ()+runGcc cc fps o =+ void $ readCreateProcess ((proc (show cc) (fps ++ ["-o", o])) { std_err = Inherit }) ""++compileOutput :: FilePath+ -> FilePath+ -> IO BSL.ByteString+compileOutput fp harness =+ withSystemTempDirectory "kmp" $ \dir -> do+ let oFile = dir </> "kempe.o"+ exe = dir </> "kempe"+ compiler = case arch of+ "x86_64" -> compile+ "aarch64" -> armCompile+ _ -> error "Internal error in test suite! Must run on either x86_64 or aarch64"+ compiler fp oFile False+ runGcc CC [oFile, harness] exe+ readExe exe+ where readExe fp' = ASCII.pack <$> readCreateProcess ((proc fp' []) { std_err = Inherit }) ""++crossCompileOutput :: FilePath+ -> FilePath+ -> IO BSL.ByteString+crossCompileOutput fp harness =+ withSystemTempDirectory "kmp" $ \dir -> do+ let oFile = dir </> "kempe.o"+ exe = dir </> "kempe"+ armCompile fp oFile False+ runGcc ArmCC [oFile, harness] exe+ readExe exe+ where readExe fp' = ASCII.pack <$> readCreateProcess ((proc "qemu-aarch64-static" [fp']) { std_err = Inherit, env = qemuEnv }) ""+ qemuEnv = Just [("QEMU_LD_PREFIX", "/usr/aarch64-linux-gnu/")]++goldenOutput :: FilePath -- ^ Kempe file+ -> FilePath -- ^ C test harness+ -> FilePath -- ^ Golden file path+ -> TestTree+goldenOutput kFp cFp golden =+ goldenVsString kFp golden (compileOutput kFp cFp)++crossGolden :: FilePath -- ^ Kempe file+ -> FilePath -- ^ C test harness+ -> FilePath -- ^ Golden file path+ -> TestTree+crossGolden kFp cFp golden =+ goldenVsString kFp golden (crossCompileOutput kFp cFp)
kempe.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: kempe-version: 0.2.0.4+version: 0.2.0.5 license: BSD-3-Clause license-file: LICENSE copyright: Copyright: (c) 2020-2021 Vanessa McHale@@ -12,6 +12,7 @@ build-type: Simple data-files: test/data/*.kmp+ test/data/diamond/*.kmp test/err/*.kmp test/examples/*.kmp test/golden/*.out@@ -208,7 +209,7 @@ test-suite kempe-golden type: exitcode-stdio-1.0 main-is: Golden.hs- hs-source-dirs: test+ hs-source-dirs: golden other-modules: Harness default-language: Haskell2010 ghc-options: -threaded -rtsopts "-with-rtsopts=-N -K1K" -Wall
lib/either.kmp view
@@ -3,6 +3,14 @@ type Either a b { Left a | Right b } +fromRight : b ((Either a) b) -- b+ =: [+ { case+ | Left -> drop+ | Right -> dip(drop)+ }+]+ isLeft : ((Either a) b) -- Bool =: [ { case
lib/maybe.kmp view
@@ -1,5 +1,13 @@ type Maybe a { Just a | Nothing } +fromMaybe : a (Maybe a) -- a+ =: [+ { case+ | Just -> dip(drop)+ | Nothing ->+ }+]+ isJust : (Maybe a) -- Bool =: [ { case
src/Kempe/Asm/Arm/ControlFlow.hs view
@@ -79,6 +79,12 @@ ; l_i <- lookupLabel l ; pure (BranchLink (ControlAnn i [l_i] IS.empty IS.empty) l : nextAsms) }+addControlFlow ((Branch _ l):asms) = do+ { i <- getFresh+ ; nextAsms <- addControlFlow asms+ ; l_i <- lookupLabel l+ ; pure (Branch (ControlAnn i [l_i] IS.empty IS.empty) l : nextAsms)+ } addControlFlow (Ret{}:asms) = do { i <- getFresh ; nextAsms <- addControlFlow asms
src/Kempe/Check/Lint.hs view
@@ -8,6 +8,8 @@ lint :: Declarations a b b -> Maybe (Warning b) lint = foldMapAlternative lintDecl +-- TODO: lint for something like dip(0) -> replace with 0 swap+ lintDecl :: KempeDecl a b b -> Maybe (Warning b) lintDecl Export{} = Nothing lintDecl TyDecl{} = Nothing
src/Kempe/IR.hs view
@@ -254,6 +254,7 @@ ret <- newLabel let meat' = (++ [Jump ret]) . toList <$> meat pure $ dataPointerDec decSz : concatMap toList switches ++ concat meat' ++ [Labeled ret]+ -- TODO: why dataPointerDec decSz?? zipWithM :: (Applicative m) => (a -> b -> m c) -> NonEmpty a -> NonEmpty b -> m (NonEmpty c) zipWithM f xs ys = sequenceA (NE.zipWith f xs ys)@@ -268,13 +269,15 @@ patternSwitch :: SizeEnv -> Pattern (ConsAnn MonoStackType) MonoStackType -> Label -> [Stmt] patternSwitch _ (PatternBool _ True) l = [MJump (Mem 1 (Reg DataPointer)) l] patternSwitch _ (PatternBool _ False) l = [MJump (EqByte (Mem 1 (Reg DataPointer)) (ConstTag 0)) l]-patternSwitch _ (PatternWildcard _) l = [Jump l]+patternSwitch _ (PatternWildcard _) l = [Jump l] -- FIXME: what about padding? when standing in for a constructor... patternSwitch _ (PatternInt _ i) l = [MJump (ExprIntRel IntEqIR (Mem 8 (Reg DataPointer)) (ConstInt $ fromInteger i)) l] patternSwitch env (PatternCons ann@(ConsAnn _ tag' _) _) l = let padAt = padBytes env ann + 1 -- decrement by padAt bytes (to discard padding), then we need to access -- the tag at [datapointer+padAt] when we check in [ dataPointerDec padAt, MJump (EqByte (Mem 1 (ExprIntBinOp IntPlusIR (Reg DataPointer) (ConstInt padAt))) (ConstTag tag')) l]+ -- FIXME: do we need dataPointerInc padAt at the end? not all+ -- constructors will have the same padding, it will fall through... -- | Constructors may need to be padded, this computes the number of bytes of -- padding
src/Kempe/IR/Opt.hs view
@@ -43,12 +43,12 @@ ((MovTemp DataPointer (ExprIntBinOp IntPlusIR (Reg DataPointer) (ConstInt i))) :(MovTemp DataPointer (ExprIntBinOp IntMinusIR (Reg DataPointer) (ConstInt i'))) :ss) =- MovTemp DataPointer (ExprIntBinOp IntMinusIR (Reg DataPointer) (ConstInt $ i-i')) : successiveBumps ss+ MovTemp DataPointer (ExprIntBinOp IntPlusIR (Reg DataPointer) (ConstInt $ i-i')) : successiveBumps ss successiveBumps ((MovTemp DataPointer (ExprIntBinOp IntMinusIR (Reg DataPointer) (ConstInt i))) :(MovTemp DataPointer (ExprIntBinOp IntPlusIR (Reg DataPointer) (ConstInt i')))- :ss) =- MovTemp DataPointer (ExprIntBinOp IntMinusIR (Reg DataPointer) (ConstInt $ i'-i)) : successiveBumps ss+ :ss) = -- TODO: is this particular one right?+ MovTemp DataPointer (ExprIntBinOp IntMinusIR (Reg DataPointer) (ConstInt $ i-i')) : successiveBumps ss successiveBumps (st@(MovMem e0 k (Mem 8 e1)) :(MovMem e0' k' (Mem 8 e1'))@@ -74,11 +74,18 @@ liftOptE [] = [] liftOptE ((MovMem e0 sz e1) : ss) = MovMem (optE e0) sz (optE e1) : liftOptE ss liftOptE ((MovTemp t e) : ss) = MovTemp t (optE e) : liftOptE ss+liftOptE ((MJump e l) : ss) = MJump (optE e) l : liftOptE ss+liftOptE ((CJump e l0 l1) : ss) = CJump (optE e) l0 l1 : liftOptE ss liftOptE (s:ss) = s : liftOptE ss optE :: Exp -> Exp optE (ExprIntBinOp IntPlusIR e (ConstInt 0)) = optE e optE (ExprIntBinOp IntMinusIR e (ConstInt 0)) = optE e+optE (BoolBinOp op e e') = BoolBinOp op (optE e) (optE e')+optE (Mem sz e) = Mem sz (optE e)+optE (PopcountIR e) = PopcountIR (optE e)+optE (IntNegIR e) = IntNegIR (optE e)+optE (EqByte e e') = EqByte (optE e) (optE e') optE e = e removeNop :: [Stmt] -> [Stmt]
src/Kempe/TyAssign.hs view
@@ -492,7 +492,7 @@ tyPattern :: Pattern b a -> TypeM () (StackType ()) tyPattern PatternWildcard{} = do aN <- dummyName "a"- pure $ StackType (S.singleton aN) [TyVar () aN] []+ pure $ StackType (S.singleton aN) [TyVar () aN] [] -- FIXME: this is wrong for constructors, could be a -- b c (for instance) tyPattern PatternInt{} = pure $ StackType S.empty [TyBuiltin () TyInt] [] tyPattern PatternBool{} = pure $ StackType S.empty [TyBuiltin () TyBool] [] tyPattern (PatternCons _ tn) = renameStack . flipStackType =<< consLookup (void tn)
− test/Golden.hs
@@ -1,28 +0,0 @@-module Main (main) where--import Data.Tuple.Extra (uncurry3)-import Harness-import System.Info (arch)-import Test.Tasty--main :: IO ()-main = defaultMain $- testGroup "Golden output tests" $- fmap (uncurry3 goldenOutput) allGoldens ++ crossTests---- These are redundant on arm-crossTests :: [TestTree]-crossTests = case arch of- "x86_64" -> fmap (uncurry3 crossGolden) allGoldens- "aarch64" -> []- _ -> error "Test suite must be run on x86_64 or aarch64"--allGoldens :: [(FilePath, FilePath, FilePath)]-allGoldens =- [ ("examples/factorial.kmp", "test/harness/factorial.c", "test/golden/factorial.out")- , ("test/examples/splitmix.kmp", "test/harness/splitmix.c", "test/golden/splitmix.out")- , ("lib/numbertheory.kmp", "test/harness/numbertheory.c", "test/golden/numbertheory.out")- , ("test/examples/hamming.kmp", "test/harness/hamming.c", "test/golden/hamming.out")- , ("test/examples/bool.kmp", "test/harness/bool.c", "test/golden/bool.out")- , ("test/examples/const.kmp", "test/harness/const.c", "test/golden/const.out")- ]
− test/Harness.hs
@@ -1,72 +0,0 @@-module Harness ( goldenOutput- , crossGolden- ) where--import qualified Data.ByteString.Lazy as BSL-import qualified Data.ByteString.Lazy.Char8 as ASCII-import Data.Functor (void)-import Kempe.File-import System.FilePath ((</>))-import System.IO.Temp-import System.Info (arch)-import System.Process (CreateProcess (env, std_err), StdStream (Inherit), proc, readCreateProcess)-import Test.Tasty-import Test.Tasty.Golden (goldenVsString)-import Test.Tasty.HUnit (assertBool, testCase)--data CC = CC- | ArmCC--instance Show CC where- show CC = "cc"- show ArmCC = "aarch64-linux-gnu-gcc"--runGcc :: CC- -> [FilePath]- -> FilePath- -> IO ()-runGcc cc fps o =- void $ readCreateProcess ((proc (show cc) (fps ++ ["-o", o])) { std_err = Inherit }) ""--compileOutput :: FilePath- -> FilePath- -> IO BSL.ByteString-compileOutput fp harness =- withSystemTempDirectory "kmp" $ \dir -> do- let oFile = dir </> "kempe.o"- exe = dir </> "kempe"- compiler = case arch of- "x86_64" -> compile- "aarch64" -> armCompile- _ -> error "Internal error in test suite! Must run on either x86_64 or aarch64"- compiler fp oFile False- runGcc CC [oFile, harness] exe- readExe exe- where readExe fp' = ASCII.pack <$> readCreateProcess ((proc fp' []) { std_err = Inherit }) ""--crossCompileOutput :: FilePath- -> FilePath- -> IO BSL.ByteString-crossCompileOutput fp harness =- withSystemTempDirectory "kmp" $ \dir -> do- let oFile = dir </> "kempe.o"- exe = dir </> "kempe"- armCompile fp oFile False- runGcc ArmCC [oFile, harness] exe- readExe exe- where readExe fp' = ASCII.pack <$> readCreateProcess ((proc "qemu-aarch64-static" [fp']) { std_err = Inherit, env = qemuEnv }) ""- qemuEnv = Just [("QEMU_LD_PREFIX", "/usr/aarch64-linux-gnu/")]--goldenOutput :: FilePath -- ^ Kempe file- -> FilePath -- ^ C test harness- -> FilePath -- ^ Golden file path- -> TestTree-goldenOutput kFp cFp golden =- goldenVsString kFp golden (compileOutput kFp cFp)--crossGolden :: FilePath -- ^ Kempe file- -> FilePath -- ^ C test harness- -> FilePath -- ^ Golden file path- -> TestTree-crossGolden kFp cFp golden =- goldenVsString kFp golden (crossCompileOutput kFp cFp)
test/Type.hs view
@@ -27,6 +27,7 @@ , tyInfer "lib/gaussian.kmp" , tyInfer "test/data/transitive.kmp" , tyInfer "lib/tuple.kmp"+ , tyInfer "test/data/type.kmp" , badType "test/err/merge.kmp" "Type a_5 -- Int a_4 is not as general as type a_3 -- a_3 a_3" , badType "test/err/kind.kmp" "Ill-kinded type: '(Maybe_1 Maybe_1)'. Note that type variables have kind \11089 in Kempe." , badType "test/err/patternMatch.kmp" "Inexhaustive pattern match."
+ test/data/badCodegen.kmp view
@@ -0,0 +1,15 @@+import "lib/maybe.kmp"++id0 : Int -- Int+ =: [ Just dip(0) fromMaybe ]++id1 : Int -- Int+ =: [ Just {case | Nothing -> 0 | Just ->} ]++id2 : Int -- Int+ =: [ Just 0 swap {case | Just -> dip(drop) | Nothing ->} ]+ ; Just 0 swap drop swap works++%foreign cabi id0+%foreign cabi id1+%foreign cabi id2
+ test/data/diamond/a.kmp view
@@ -0,0 +1,7 @@+import "test/data/diamond/c.kmp"+import "test/data/diamond/b.kmp"++forExport : -- Int+ =: [ res 2 * ]++%foreign cabi forExport
+ test/data/diamond/b.kmp view
@@ -0,0 +1,2 @@+rand : -- Int+ =: $cfun"rand"
+ test/data/diamond/c.kmp view
@@ -0,0 +1,4 @@+import "test/data/diamond/d.kmp"++res : -- Int+ =: [ rand 1 + ]
+ test/data/diamond/d.kmp view
@@ -0,0 +1,2 @@+rand : -- Int+ =: [ 17 ]
+ test/data/type.kmp view
@@ -0,0 +1,4 @@+import"lib/maybe.kmp"++id1 : Int -- Int+ =: [ Just {case | Nothing -> 0 | _ ->} ]
test/golden/gaussian.ir view
@@ -6,7 +6,7 @@ (movmem (+ (reg datapointer) (int 16)) (mem [1] (+ (reg datapointer) (int 33)))) (movmem (reg datapointer) (mem [8] (- (reg datapointer) (int 24)))) (movmem (- (reg datapointer) (int 24)) (mem [8] (- (reg datapointer) (int 16))))-(movmem (- (reg datapointer) (int 16)) (mem [8] (- (reg datapointer) (int 0))))+(movmem (- (reg datapointer) (int 16)) (mem [8] (reg datapointer))) (movtemp datapointer (- (reg datapointer) (int 8))) (movtemp t_1 (mem [8] (reg datapointer))) (movtemp datapointer (- (reg datapointer) (int 8)))@@ -31,7 +31,6 @@ (movmem (- (reg datapointer) (int 17)) (mem [8] (- (reg datapointer) (int 34)))) (movmem (- (reg datapointer) (int 9)) (mem [8] (- (reg datapointer) (int 26)))) (movmem (- (reg datapointer) (int 1)) (mem [1] (- (reg datapointer) (int 18))))-(movmem (reg datapointer) (mem [8] (- (reg datapointer) (int 0)))) (movtemp datapointer (+ (reg datapointer) (int 17))) (movmem (reg datapointer) (mem [8] (- (reg datapointer) (int 34)))) (movmem (+ (reg datapointer) (int 8)) (mem [8] (- (reg datapointer) (int 26))))@@ -39,7 +38,7 @@ (movmem (- (reg datapointer) (int 34)) (mem [8] (- (reg datapointer) (int 17)))) (movmem (- (reg datapointer) (int 26)) (mem [8] (- (reg datapointer) (int 9)))) (movmem (- (reg datapointer) (int 18)) (mem [1] (- (reg datapointer) (int 1))))-(movmem (- (reg datapointer) (int 17)) (mem [8] (- (reg datapointer) (int 0))))+(movmem (- (reg datapointer) (int 17)) (mem [8] (reg datapointer))) (movmem (- (reg datapointer) (int 9)) (mem [8] (+ (reg datapointer) (int 8)))) (movmem (- (reg datapointer) (int 1)) (mem [1] (+ (reg datapointer) (int 16)))) (movmem (reg datapointer) (mem [8] (- (reg datapointer) (int 17))))@@ -48,7 +47,6 @@ (movmem (- (reg datapointer) (int 17)) (mem [8] (- (reg datapointer) (int 34)))) (movmem (- (reg datapointer) (int 9)) (mem [8] (- (reg datapointer) (int 26)))) (movmem (- (reg datapointer) (int 1)) (mem [1] (- (reg datapointer) (int 18))))-(movmem (reg datapointer) (mem [8] (- (reg datapointer) (int 0)))) (movtemp datapointer (+ (reg datapointer) (int 17))) (movmem (reg datapointer) (mem [8] (- (reg datapointer) (int 34)))) (movmem (+ (reg datapointer) (int 8)) (mem [8] (- (reg datapointer) (int 26))))@@ -56,7 +54,7 @@ (movmem (- (reg datapointer) (int 34)) (mem [8] (- (reg datapointer) (int 17)))) (movmem (- (reg datapointer) (int 26)) (mem [8] (- (reg datapointer) (int 9)))) (movmem (- (reg datapointer) (int 18)) (mem [1] (- (reg datapointer) (int 1))))-(movmem (- (reg datapointer) (int 17)) (mem [8] (- (reg datapointer) (int 0))))+(movmem (- (reg datapointer) (int 17)) (mem [8] (reg datapointer))) (movmem (- (reg datapointer) (int 9)) (mem [8] (+ (reg datapointer) (int 8)))) (movmem (- (reg datapointer) (int 1)) (mem [1] (+ (reg datapointer) (int 16)))) (movtemp datapointer (- (reg datapointer) (int 34)))@@ -73,7 +71,7 @@ (movtemp datapointer (+ (reg datapointer) (int 8))) (movmem (reg datapointer) (mem [8] (- (reg datapointer) (int 16)))) (movmem (- (reg datapointer) (int 16)) (mem [8] (- (reg datapointer) (int 8))))-(movmem (- (reg datapointer) (int 8)) (mem [8] (- (reg datapointer) (int 0))))+(movmem (- (reg datapointer) (int 8)) (mem [8] (reg datapointer))) (movtemp datapointer (- (reg datapointer) (int 16))) (movtemp t_7 (mem [8] (reg datapointer))) (movtemp datapointer (- (reg datapointer) (int 8)))@@ -85,17 +83,16 @@ (movtemp datapointer (- (reg datapointer) (int 8))) (movtemp t_10 (mem [8] (reg datapointer))) (movmem (reg datapointer) (+ (reg t_10) (reg t_9)))-(movtemp datapointer (- (reg datapointer) (int 0)))+(movtemp datapointer (+ (reg datapointer) (int -34))) (movmem (reg datapointer) (mem [8] (+ (reg datapointer) (int 25)))) (movmem (+ (reg datapointer) (int 8)) (mem [8] (+ (reg datapointer) (int 33)))) (movmem (+ (reg datapointer) (int 16)) (mem [8] (+ (reg datapointer) (int 41)))) (movmem (+ (reg datapointer) (int 24)) (mem [1] (+ (reg datapointer) (int 49))))-(movtemp datapointer (- (reg datapointer) (int 34))) (movmem (reg datapointer) (mem [8] (+ (reg datapointer) (int 8)))) (movtemp datapointer (+ (reg datapointer) (int 8))) (movmem (reg datapointer) (mem [8] (- (reg datapointer) (int 32)))) (movmem (- (reg datapointer) (int 32)) (mem [8] (- (reg datapointer) (int 24))))-(movmem (- (reg datapointer) (int 24)) (mem [8] (- (reg datapointer) (int 0))))+(movmem (- (reg datapointer) (int 24)) (mem [8] (reg datapointer))) (movtemp datapointer (- (reg datapointer) (int 16))) (movtemp t_11 (mem [8] (reg datapointer))) (movtemp datapointer (- (reg datapointer) (int 8)))@@ -103,7 +100,7 @@ (movmem (reg datapointer) (* (reg t_12) (reg t_11))) (movtemp datapointer (+ (reg datapointer) (int 8))) (movmem (reg datapointer) (mem [8] (+ (reg datapointer) (int 8))))-(movtemp datapointer (- (reg datapointer) (int 0)))+(movtemp datapointer (+ (reg datapointer) (int -16))) (movtemp t_13 (mem [8] (reg datapointer))) (movtemp datapointer (- (reg datapointer) (int 8))) (movtemp t_14 (mem [8] (reg datapointer)))@@ -111,7 +108,6 @@ (movtemp datapointer (+ (reg datapointer) (int 8))) (movmem (reg datapointer) (mem [8] (+ (reg datapointer) (int 16)))) (movmem (+ (reg datapointer) (int 8)) (mem [8] (+ (reg datapointer) (int 24))))-(movtemp datapointer (- (reg datapointer) (int 16))) (movtemp t_15 (mem [8] (reg datapointer))) (movtemp datapointer (- (reg datapointer) (int 8))) (movtemp t_16 (mem [8] (reg datapointer)))
+ test/golden/id.out view
@@ -0,0 +1,3 @@+4+4+4
+ test/harness/id.c view
@@ -0,0 +1,11 @@+#include <stdio.h>++extern int id0(int);+extern int id1(int);+extern int id2(int);++int main(int argc, char *argv[]) {+ printf("%d\n", id0(4));+ printf("%d\n", id1(4));+ printf("%d", id2(4));+}