Commit d53be3b6 authored by Edward Z. Yang's avatar Edward Z. Yang
Browse files

New and improved tests for #5435. Linux only at the moment.



Added a new test Makefile variable $(dllext), which is
instantiated to .dll or .so or .dylib depending on your platform.
Signed-off-by: Edward Z. Yang's avatarEdward Z. Yang <ezyang@mit.edu>
parent 9b0f0cb0
......@@ -37,6 +37,14 @@ else
exeext = .exe
endif
ifneq "$(filter $(TargetOS_CPP),cygwin32 mingw32)" ""
dllext = .dll
else ifeq "$(TargetOS_CPP)" "darwin"
dllext = .dylib
else
dllext = .so
endif
RUNTEST_OPTS += -e ghc_compiler_always_flags="'$(TEST_HC_OPTS)'"
RUNTEST_OPTS += -e ghc_debugged=$(GhcDebugged)
......
......@@ -45,30 +45,41 @@ T5423:
"$(TEST_HC)" $(TEST_HC_OPTS) -v0 T5423.o T5423_cmm.o -o T5423$(exeext)
./T5423
.PHONY: T5435_v
T5435_v:
$(RM) T5435_c_v.o T5435_v$(exeext)
'$(TEST_HC)' $(TEST_HC_OPTS) -v0 -c T5435.c -o T5435_c_v.o
'$(TEST_HC)' $(TEST_HC_OPTS) -v0 T5435.hs -osuf v_o -o T5435_v$(exeext)
./T5435_v v ./T5435_c_v.o
# This doesn't work on Windows, which expects *no* file extension
# File extension here is not right for Mac OS X, where it should be dylib.
# Note that this is DLL-loading from a *static* executable; we probably
# also ought to provide the dynamic way via the usual channels.
.PHONY: T5435_dyn
T5435_dyn:
$(RM) T5435_c_dyn.o T5435_dyn$(exeext)
'$(TEST_HC)' $(filter-out -rtsopts, $(TEST_HC_OPTS)) -v0 -fPIC -shared -c T5435.c -osuf dyn_o -o T5435_c.so
'$(TEST_HC)' $(TEST_HC_OPTS) -v0 T5435.hs -osuf dyn_o -o T5435_dyn$(exeext)
./T5435_dyn dyn ./T5435_c.so
.PHONY: T5435_dyn_mingw32
T5435_dyn_mingw32:
$(RM) T5435_c_dyn.o T5435_dyn$(exeext)
'$(TEST_HC)' $(filter-out -rtsopts, $(TEST_HC_OPTS)) -v0 -fPIC -shared -c T5435.c -osuf dyn_o -o T5435_c.dll
'$(TEST_HC)' $(TEST_HC_OPTS) -v0 T5435.hs -osuf dyn_o -o T5435_dyn$(exeext)
./T5435_dyn dyn ./T5435_c
# Naming convention: 'T5423_' obj-way '_' obj-src
# obj-way ::= v | dyn
# obj-src ::= gcc // using __attribute__(constructor)
# | asm // manually laid out sections
# $(0) = obj-src
define run_T5435_v
$(RM) T5435_load_v_$(1) T5435_v_$(1)$(exeext)
'$(TEST_HC)' $(TEST_HC_OPTS) -v0 -c T5435_$(1).c -o T5435_load_v_$(1).o
'$(TEST_HC)' $(TEST_HC_OPTS) -v0 T5435.hs -osuf main_v_$(1)_o -o T5435_v_$(1)$(exeext)
./T5435_v_$(1) v ./T5435_load_v_$(1).o
endef
define run_T5435_dyn
$(RM) T5435_load_dyn_$(1) T5435_dyn_$(1)$(exeext)
'$(TEST_HC)' $(filter-out -rtsopts, $(TEST_HC_OPTS)) -v0 -fPIC -shared -c T5435_$(1).c -osuf dyn_$(1)_o -o T5435_load_dyn_$(1)$(dllext)
'$(TEST_HC)' $(TEST_HC_OPTS) -v0 T5435.hs -osuf main_dyn_$(1)_o -o T5435_dyn_$(1)$(exeext)
./T5435_dyn_$(1) dyn ./T5435_load_dyn_$(1)$(dllext)
endef
.PHONY: T5435_v_gcc
T5435_v_gcc :
$(call run_T5435_v,gcc)
.PHONY: T5435_v_asm
T5435_v_asm :
$(call run_T5435_v,asm)
.PHONY: T5435_dyn_gcc
T5435_dyn_gcc :
$(call run_T5435_dyn,gcc)
.PHONY: T5435_dyn_asm
T5435_dyn_asm :
$(call run_T5435_dyn,asm)
T6006_setup :
'$(TEST_HC)' $(TEST_HC_OPTS) -c T6006.hs
......
......@@ -2,8 +2,10 @@
import Foreign.C.String
import Control.Monad
import System.Environment
import System.FilePath
import Foreign.Ptr
-- Type of paths is different on Windows
#if defined(mingw32_HOST_OS)
type PathString = CWString
withPathString = withCWString
......@@ -12,12 +14,22 @@ type PathString = CString
withPathString = withCString
#endif
mungeDLL :: FilePath -> FilePath
#if defined(mingw32_HOST_OS) || defined(cygwin32_HOST_OS)
-- Strip extension because addDLL on Windows doesn't want it
mungeDLL f =
let (base, ext) = splitExtension f
in if ext == ".dll" then base else error ("unexpected DLL file name: " ++ f)
#else
mungeDLL = id
#endif
main = do
[ty, object] <- getArgs
initLinker
if ty == "dyn"
then do
r <- withPathString object $ \s -> addDLL s
r <- withPathString (mungeDLL object) $ \s -> addDLL s
when (r /= nullPtr) $ error =<< peekCString r
else do
r <- withPathString object $ \s -> loadObj s
......@@ -26,6 +38,22 @@ main = do
when (r /= 1) $ error "resolveObj failed"
putStrLn "success"
{-
f <- withCString (mungeSymbol "do_checks") lookupSymbol
when (f == nullFunPtr) $ error "lookupSymbol failed"
mkIO f
foreign import ccall "lookupSymbol" lookupSymbol :: CString -> IO (FunPtr (IO ()))
foreign import ccall "dynamic" mkIO :: FunPtr (IO ()) -> IO ()
mungeSymbol :: String -> String
#if LEADING_UNDERSCORE
mungeSymbol s = "_" ++ s -- Mac OS X
#else
mungeSymbol = id
#endif
-}
foreign import ccall "initLinker" initLinker :: IO ()
foreign import ccall "addDLL" addDLL :: PathString -> IO CString
foreign import ccall "loadObj" loadObj :: PathString -> IO Int
......
#include <stdio.h>
// flush so that:
// (1) if we segfault, we'll see the output
// (2) we get ordered correctly with Haskell output, which uses
// different buffers
static void initArray1(void) { printf("initArray1\n"); fflush(stdout); }
static void initArray2(void) { printf("initArray2\n"); fflush(stdout); }
static void ctors1(void) { printf("ctors1\n"); fflush(stdout); }
static void ctors2(void) { printf("ctors2\n"); fflush(stdout); }
#if defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS)
#error "Not implemented yet!"
#elif defined(darwin_HOST_OS)
#error "Not implemented yet!"
#else /* ELF */
static void (*const init_array[2])(void) __attribute__((
section(".init_array"), // put it in the right section
used, // prevent GCC from optimizing this away
aligned(sizeof(void*)) // avoid slop between GCC's preloaded initializers and ours
))
= {initArray1, initArray2};
static void (*ctors[2])(void) __attribute__((
section(".ctors"),
used,
aligned(sizeof(void*))))
= {ctors2, ctors1}; // ctors run in reverse
#endif
initArray1
initArray2
ctors1
ctors2
success
#include <stdio.h>
static void initializer(void) __attribute__((constructor));
static void initializer(void) __attribute__((constructor));
static void initializer(void)
{
printf("initializer run\n");
......
initArray1
initArray2
ctors1
ctors2
success
......@@ -130,20 +130,13 @@ test('T5423',
run_command,
['$MAKE -s --no-print-directory T5423'])
test('T5435_v',
extra_clean(['T5435_c_v.o']),
run_command,
['$MAKE -s --no-print-directory T5435_v'])
test('T5435_dyn',
[when(opsys('mingw32'), skip), extra_clean(['T5435_c.so'])],
run_command,
['$MAKE -s --no-print-directory T5435_dyn'])
# These should have extra_clean() arguments, but I need
# to somehow extract out the name of DLLs to do that
test('T5435_dyn_mingw32',
[when(not opsys('mingw32'), skip), extra_clean(['T5435_c.dll'])],
run_command,
['$MAKE -s --no-print-directory T5435_dyn_mingw32'])
test('T5435_v_asm', normal, run_command, ['$MAKE -s --no-print-directory T5435_v_asm'])
test('T5435_v_gcc', normal, run_command, ['$MAKE -s --no-print-directory T5435_v_gcc'])
test('T5435_dyn_asm', normal, run_command, ['$MAKE -s --no-print-directory T5435_dyn_asm'])
test('T5435_dyn_gcc', normal, run_command, ['$MAKE -s --no-print-directory T5435_dyn_gcc'])
test('T5993', extra_run_opts('+RTS -k8 -RTS'), compile_and_run, [''])
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment