--- /dev/null
+for a debug build, use
+$ DBGFLAGS='-DDBG_JIT -DDBG_BB' make tests/Fib.dbg
+
+`make clean' is needed if you change $DBGFLAGS.
+for all available flags, see `debug.h'.
PACKAGES_ := bytestring harpy hs-java
PACKAGES := $(addprefix -package ,$(PACKAGES_))
-GHC_OPT := -dynamic -Wall -O0 -fno-warn-unused-do-bind
+GHC_OPT := -I. -dynamic -Wall -O0 -fno-warn-unused-do-bind
GHC_LD := -optl-Xlinker -optl-x
%.dbg: %.class mate.dbg
./mate.dbg $(basename $<)
+ifeq (${DBGFLAGS},)
+DEBUGFLAGS = -DDBG_JIT -DDBG_MP
+else
+DEBUGFLAGS = ${DBGFLAGS}
+endif
mate.dbg: Mate.hs ffi/trap.c $(HS_FILES) $(HS_BOOT) ffi/native.o
@mkdir -p build/debug/{ffi,Mate,}
- gcc -Wall -DDEBUG -O0 -c ffi/trap.c -o build/debug/ffi/trap.o
- ghc --make -DDEBUG $(GHC_OPT) Mate.hs build/debug/ffi/trap.o -o $@ $(GHC_LD) -outputdir build/debug
+ gcc -Wall $(DEBUGFLAGS) -O0 -c ffi/trap.c -o build/debug/ffi/trap.o
+ ghc --make $(DEBUGFLAGS) $(GHC_OPT) Mate.hs build/debug/ffi/trap.o -o $@ $(GHC_LD) -outputdir build/debug
clean:
rm -rf build mate mate.dbg ffi/native.o tests/*.class
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
+#include "debug.h"
module Main where
import System.Environment
#ifdef DEBUG
import Text.Printf
-
-import JVM.Dump
#endif
import JVM.ClassFile
[clspath] -> do
let bclspath = B.pack $ map (fromIntegral . ord) clspath
cls <- getClassFile bclspath
-#ifdef DEBUG
- dumpClass cls
-#endif
hmap <- parseMethod cls "main"
case hmap of
Just hmap' -> do
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
+#include "debug.h"
module Mate.BasicBlocks(
BlockID,
BasicBlock (..),
BBEnd (..),
MapBB,
-#ifdef DEBUG
+#ifdef DBG_BB
printMapBB,
test_main,
#endif
import Mate.Utilities
import Mate.Types
+import Mate.Debug
#ifdef DEBUG
import Text.Printf
type OffIns = (Offset, Instruction)
-#ifdef DEBUG
+#ifdef DBG_BB
printMapBB :: Maybe MapBB -> IO ()
printMapBB Nothing = putStrLn "No BasicBlock"
printMapBB (Just hmap) = do
Nothing -> error $ "BlockID " ++ show i ++ " not found."
#endif
-#ifdef DEBUG
+#ifdef DBG_BB
testInstance :: String -> B.ByteString -> IO ()
testInstance cf method = do
cls <- parseClassFile cf
printMapBB hmap
#endif
-#ifdef DEBUG
+#ifdef DBG_BB
test_main :: IO ()
test_main = do
test_01
parseMethod :: Class Resolved -> B.ByteString -> IO (Maybe MapBB)
parseMethod cls method = do
let maybe_bb = testCFG $ lookupMethod method cls
-#ifdef DEBUG
- putStr "BB: analysing: "
let msig = methodSignature $ (classMethods cls) !! 1
- putStrLn $ toString (method `B.append` ": " `B.append` (encode msig))
+ printf_bb "BB: analysing \"%s\"\n" $ toString (method `B.append` ": " `B.append` (encode msig))
+#ifdef DBG_BB
printMapBB maybe_bb
#endif
-#ifdef DEBUG
-- small example how to get information about
-- exceptions of a method
-- TODO: remove ;-)
let (Just m) = lookupMethod method cls
case attrByName m "Code" of
- Nothing -> printf "exception: no handler for this method\n"
- Just exceptionstream -> printf "exception: \"%s\"\n" (show $ codeExceptions $ decodeMethod exceptionstream)
-#endif
+ Nothing -> printf_bb "exception: no handler for this method\n"
+ Just exceptionstream -> printf_bb "exception: \"%s\"\n" (show $ codeExceptions $ decodeMethod exceptionstream)
return maybe_bb
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ForeignFunctionInterface #-}
+#include "debug.h"
module Mate.ClassPool (
getClassInfo,
getClassFile,
#ifdef DEBUG
import Text.Printf
#endif
+#ifdef DBG_CLASS
+import JVM.Dump
+#endif
import Foreign.Ptr
import Foreign.C.Types
import {-# SOURCE #-} Mate.MethodPool
import Mate.Types
import Mate.Utilities
+import Mate.Debug
getClassInfo :: B.ByteString -> IO ClassInfo
getClassInfo path = do
Just w32 -> return $ (+4) w32
Nothing -> error $ "getInterfaceMethodOffset: no offset set"
+
loadClass :: B.ByteString -> IO ClassInfo
loadClass path = do
-#ifdef DEBUG
- printf "loadClass: \"%s\"\n" $ toString path
-#endif
let rpath = toString $ path `B.append` ".class"
cfile <- parseClassFile rpath
+#ifdef DBG_CLASS
+ dumpClass cfile
+#endif
-- load all interfaces, which are implemented by this class
sequence_ [ loadInterface i | i <- interfaces cfile ]
superclass <- case (path /= "java/lang/Object") of
let w32_iftable = fromIntegral $ ptrToIntPtr iftable :: Word32
-- store interface-table at offset 0 in method-table
pokeElemOff (intPtrToPtr $ fromIntegral mbase) 0 w32_iftable
-#ifdef DEBUG
- printf "staticmap: %s @ %s\n" (show staticmap) (toString path)
- printf "fieldmap: %s @ %s\n" (show fieldmap) (toString path)
- printf "methodmap: %s @ %s\n" (show methodmap) (toString path)
- printf "mbase: 0x%08x\n" mbase
- printf "interfacemethod: %s @ %s\n" (show immap) (toString path)
- printf "iftable: 0x%08x\n" w32_iftable
-#endif
+ printf_cp "staticmap: %s @ %s\n" (show staticmap) (toString path)
+ printf_cp "fieldmap: %s @ %s\n" (show fieldmap) (toString path)
+ printf_cp "methodmap: %s @ %s\n" (show methodmap) (toString path)
+ printf_cp "mbase: 0x%08x\n" mbase
+ printf_cp "interfacemethod: %s @ %s\n" (show immap) (toString path)
+ printf_cp "iftable: 0x%08x\n" w32_iftable
virtual_map <- get_virtualmap >>= ptr2virtualmap
let virtual_map' = M.insert mbase path virtual_map
virtualmap2ptr virtual_map' >>= set_virtualmap
case M.lookup path imap of
Just _ -> return ()
Nothing -> do
-#ifdef DEBUG
- printf "interface: loading \"%s\"\n" $ toString path
-#endif
+ printf_cp "interface: loading \"%s\"\n" $ toString path
let ifpath = toString $ path `B.append` ".class"
cfile <- parseClassFile ifpath
-- load "superinterfaces" first
let mi = (MethodInfo "<clinit>" path (methodSignature m))
entry <- compileBB hmap' mi
addMethodRef entry mi [path]
-#ifdef DEBUG
- printf "executing static initializer from %s now\n" (toString path)
-#endif
+ printf_cp "executing static initializer from %s now\n" (toString path)
executeFuncPtr entry
-#ifdef DEBUG
- printf "static initializer from %s done\n" (toString path)
-#endif
+ printf_cp "static initializer from %s done\n" (toString path)
Nothing -> error $ "loadClass: static initializer not found (WTF?). abort"
Nothing -> return ()
--- /dev/null
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+#include "debug.h"
+
+module Mate.Debug where
+
+{- we cannot use `PrintfType' from Text.Printf, as it isn't exported.
+ - so we implement a `VarArgsFake' here.
+ - http://www.haskell.org/haskellwiki/Varargs -}
+class VarArgsFake t where
+ varFake :: [String] -> t
+
+instance VarArgsFake (IO a) where
+ varFake _ = return undefined
+
+instance (Show a, VarArgsFake r) => VarArgsFake (a -> r) where
+ varFake _ = \_ -> varFake []
+
+printf_fake :: String -> (VarArgsFake t) => t
+printf_fake _ = varFake []
+
+
+-- see counterpart at `debug.h'
+#ifndef DBG_JIT
+printf_jit :: String -> (VarArgsFake t) => t
+printf_jit = printf_fake
+#endif
+
+#ifndef DBG_BB
+printf_bb :: String -> (VarArgsFake t) => t
+printf_bb = printf_fake
+#endif
+
+#ifndef DBG_MP
+printf_mp :: String -> (VarArgsFake t) => t
+printf_mp = printf_fake
+#endif
+
+#ifndef DBG_CP
+printf_cp :: String -> (VarArgsFake t) => t
+printf_cp = printf_fake
+#endif
+
+#ifndef DBG_STR
+printf_str :: String -> (VarArgsFake t) => t
+printf_str = printf_fake
+#endif
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ForeignFunctionInterface #-}
+#include "debug.h"
module Mate.MethodPool where
import Data.Binary
import JVM.ClassFile
import Harpy
-#ifdef DEBUG
import Harpy.X86Disassembler
+#ifdef DEBUG
import Text.Printf
#endif
import Mate.X86CodeGen
import Mate.Utilities
import Mate.ClassPool
-
+import Mate.Debug
foreign import ccall "dynamic"
code_void :: FunPtr (IO ()) -> (IO ())
case M.lookup mi' mmap of
Nothing -> do
cls <- getClassFile cm
-#ifdef DEBUG
- printf "getMethodEntry(from 0x%08x): no method \"%s\" found. compile it\n" w32_from (show mi')
-#endif
+ printf_mp "getMethodEntry(from 0x%08x): no method \"%s\" found. compile it\n" w32_from (show mi')
mm <- lookupMethodRecursive method [] cls
case mm of
Just (mm', clsnames, cls') -> do
True -> do
-- TODO(bernhard): cleaner please... *do'h*
let symbol = (replace "/" "_" $ toString cm) ++ "__" ++ (toString method) ++ "__" ++ (replace ";" "_" $ replace "/" "_" $ replace "(" "_" (replace ")" "_" $ toString $ encode sig))
-#ifdef DEBUG
- printf "native-call: symbol: %s\n" symbol
-#endif
+ printf_mp "native-call: symbol: %s\n" symbol
nf <- loadNativeFunction symbol
let w32_nf = fromIntegral nf
let mmap' = M.insert mi' w32_nf mmap
let tmap' = M.union tmap new_tmap -- prefers elements in cmap
trapmap2ptr tmap' >>= set_trapmap
-#ifdef DEBUG
- printf "disasm:\n"
- mapM_ (putStrLn . showAtt) (snd right)
-#endif
+ printf_jit "generated code of \"%s\":\n" (toString $ methName methodinfo)
+ mapM_ (printf_jit "%s\n" . showAtt) (snd right)
+ printf_jit "\n\n"
-- UNCOMMENT NEXT LINE FOR GDB FUN
-- _ <- getLine
-- (1) start it with `gdb ./mate' and then `run <classfile>'
+#include "debug.h"
module Mate.RegisterAllocation where
import Data.List
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ForeignFunctionInterface #-}
+#include "debug.h"
module Mate.Strings (
getUniqueStringAddr
) where
import Foreign.Marshal.Array
import Mate.Types
+import Mate.Debug
getUniqueStringAddr :: B.ByteString -> IO Word32
BI.memset newstr 0 (fromIntegral $ strlen + 1)
copyBytes newstr arr strlen
let w32_ptr = fromIntegral $ ptrToIntPtr newstr
-#ifdef DEBUG
- printf "new str ptr: 0x%08x (%s)@%d\n" w32_ptr (toString str) strlen
-#endif
+ printf_str "new str ptr: 0x%08x (%s)@%d\n" w32_ptr (toString str) strlen
return w32_ptr
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ForeignFunctionInterface #-}
+#include "debug.h"
module Mate.X86CodeGen where
import Data.Binary
--- /dev/null
+/* DBG_JIT .... see generated code and CodeGen information
+ * DBG_BB ..... BasicBlock information
+ * DBG_MP ..... MethodPool.hs
+ * DBG_CP ..... ClassPool.hs
+ * DBG_STR .... Strings.hs
+ * // no printf_* defined
+ * DBG_TRAP ... show information @ trap.c
+ * DBG_CLASS .. dump classfile
+ */
+
+/* ooops defines */
+#ifdef BG_JIT
+#define DBG_JIT
+#endif
+
+#ifdef BG_BB
+#define DBG_BB
+#endif
+
+#ifdef BG_MP
+#define DBG_MP
+#endif
+
+#ifdef BG_CP
+#define DBG_CP
+#endif
+
+#ifdef BG_STR
+#define DBG_STR
+#endif
+
+#ifdef BG_TRAP
+#define DBG_TRAP
+#endif
+
+#ifdef BG_CLASS
+#define DBG_CLASS
+#endif
+
+/* if one constant from above is defined, we want to import
+ * libraries like Text.Printf
+ * needed for gettting proper `-Wall' output on a release build */
+
+#if defined(DBG_JIT) || defined(DBG_BB) || defined(DBG_MP) || defined(DBG_CP) || defined(DBG_STR)
+#define DEBUG
+#endif
+
+/* it would be awesome if we could just write
+ * > printf_fake = printf
+ * here, but the type can't be infered, since `PrintfType'
+ * isn't visible (at least this is my explanation :/).
+ * if I'm wrong, move this to `Mate/Debug.hs'
+ */
+#ifdef DBG_JIT
+#define printf_jit printf
+#endif
+
+#ifdef DBG_BB
+#define printf_bb printf
+#endif
+
+#ifdef DBG_MP
+#define printf_mp printf
+#endif
+
+#ifdef DBG_CP
+#define printf_cp printf
+#endif
+
+#ifdef DBG_STR
+#define printf_str printf
+#endif
(h) so much cleanup...
+(h) get rid of trap.c
+ -> it's C. we don't want that.
+ -> at the moment System.Posix.Signal isn't powerful enough
+ -> wait for: http://hackage.haskell.org/trac/ghc/ticket/2451
+
(l) check different types (byte, long, ...)
(l) floating point support
#include <stdio.h>
#include <stdlib.h>
+#include "../debug.h"
+
/* TODO(bernhard): use {u,}int* types */
#define __USE_GNU
unsigned int getStaticFieldAddr(unsigned int, void*);
unsigned int getTrapType(unsigned int, unsigned int);
-#ifdef DEBUG
+#ifdef DBG_TRAP
#define dprintf(args...) do { printf (args); } while (0);
#else
#define dprintf(args...)