Re: Haskell migration exp to unstable
On Mon, May 27, 2013 at 04:03:38PM +0200, Joachim Breitner wrote:
> Am Montag, den 27.05.2013, 14:39 +0100 schrieb Colin Watson:
> > I can indeed confirm that we're starting to see failures due to broken
> > GHCi, for example:
> >
> > https://buildd.debian.org/status/fetch.php?pkg=haskell-data-accessor-template&arch=armel&ver=0.2.1.10-3&stamp=1369656600
> > https://buildd.debian.org/status/fetch.php?pkg=haskell-distributive&arch=armhf&ver=0.3-2&stamp=1369561716
> >
> > Note that some of the affected packages would succeed if GHCi were
> > disabled (because doctest detects that condition and skips), so it's not
> > quite true that we'd just have to remove all the affected packages
> > anyway.
>
> how bad is the breakage of GHCi on arm anyways? Just affecting some
> packages, or unusable?
Essentially unusable.
When certain Thumb relocations are involved it often fails to even start
up (http://hackage.haskell.org/trac/ghc/ticket/7823).
On armel the R_ARM_V4BX relocation is unimplemented. This can just be
ignored, as follows, but I don't think I got round to sending this
upstream since I never managed to get the whole assemblage to work.
diff --git a/rts/Linker.c b/rts/Linker.c
index 40f5204..3a2cd03 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -4143,6 +4143,9 @@ ocResolve_PEi386 ( ObjectCode* oc )
#ifndef R_ARM_MOVW_ABS_NC
# define R_ARM_MOVW_ABS_NC 43
#endif
+#ifndef R_ARM_V4BX
+# define R_ARM_V4BX 40
+#endif
#ifndef R_ARM_MOVT_ABS
# define R_ARM_MOVT_ABS 44
#endif
@@ -5018,6 +5021,13 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
break;
}
+ case R_ARM_V4BX:
+ /* This records the location of an ARMv4t BX instruction so that
+ * a linker can transform it into MOV PC, r for ARMv4. We have
+ * no need of this and can just ignore the relocation.
+ */
+ return 0;
+
# endif // arm_HOST_ARCH
default:
You lose as soon as the interpreter tries to generate any new bytecode
(http://hackage.haskell.org/trac/ghc/ticket/7794). My work-in-progress
for this looks like the following, but I still haven't managed to get
this to work. I hear that 7.8 will completely rearrange this using
dynamic linking anyway, so my motivation to embark on further nine-hour
test builds and multi-hour debugging/head-scratching sessions for this
is pretty slim.
diff --git a/compiler/ghci/ByteCodeItbls.lhs b/compiler/ghci/ByteCodeItbls.lhs
index f152473..95be15f 100644
--- a/compiler/ghci/ByteCodeItbls.lhs
+++ b/compiler/ghci/ByteCodeItbls.lhs
@@ -241,6 +241,12 @@ mkJumpToAddr a
, fromIntegral ((w64 `shiftR` 32) .&. 0x0000FFFF) ]
where w64 = fromIntegral (ptrToInt a) :: Word64
+#elif arm_TARGET_ARCH
+type ItblCode = Word32
+mkJumpToAddr a
+ = [ 0xe51ff004 -- ldr pc, [pc, #-4] # pc reads as <current insn>+8
+ , fromIntegral (ptrToInt a) ]
+
#else
type ItblCode = Word32
mkJumpToAddr a
@@ -419,14 +425,23 @@ load = do addr <- advance
lift (peek addr)
-newExecConItbl :: DynFlags -> StgConInfoTable -> IO (FunPtr ())
-newExecConItbl dflags obj
+newExecMem :: Int -> (Ptr a -> Ptr a -> IO ()) -> IO (FunPtr ())
+newExecMem len poke_fn
= alloca $ \pcode -> do
- wr_ptr <- _allocateExec (fromIntegral (sizeOfConItbl obj)) pcode
+ wr_ptr <- _allocateExec (fromIntegral len) pcode
ex_ptr <- peek pcode
- pokeConItbl dflags wr_ptr ex_ptr obj
+ poke_fn wr_ptr ex_ptr
+ _clearExecCache (fromIntegral len) wr_ptr
return (castPtrToFunPtr ex_ptr)
+newExecConItbl :: DynFlags -> StgConInfoTable -> IO (FunPtr ())
+newExecConItbl dflags obj
+ = newExecMem (sizeOfConItbl obj) new_con_itbl where
+ new_con_itbl wr_ptr ex_ptr = pokeConItbl dflags wr_ptr ex_ptr obj
+
foreign import ccall unsafe "allocateExec"
_allocateExec :: CUInt -> Ptr (Ptr a) -> IO (Ptr a)
+
+foreign import ccall unsafe "clearExecCache"
+ _clearExecCache :: CUInt -> Ptr a -> IO ()
\end{code}
diff --git a/includes/rts/storage/GC.h b/includes/rts/storage/GC.h
index 80f11d3..8b3997a 100644
--- a/includes/rts/storage/GC.h
+++ b/includes/rts/storage/GC.h
@@ -156,6 +156,7 @@ StgPtr allocatePinned ( Capability *cap, W_ n );
/* memory allocator for executable memory */
void * allocateExec(W_ len, void **exec_addr);
void freeExec (void *p);
+void clearExecCache (W_ bytes, void *addr);
// Used by GC checks in external .cmm code:
extern W_ large_alloc_lim;
diff --git a/rts/Linker.c b/rts/Linker.c
index 40f5204..3a2cd03 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -1315,6 +1315,7 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(allocate) \
SymI_HasProto(allocateExec) \
SymI_HasProto(freeExec) \
+ SymI_HasProto(clearExecCache) \
SymI_HasProto(getAllocations) \
SymI_HasProto(revertCAFs) \
SymI_HasProto(RtsFlags) \
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index 5c4e54f..f2c71b8 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -1194,6 +1194,14 @@ void freeExec (void *addr)
#endif /* mingw32_HOST_OS */
+void clearExecCache (W_ bytes, void *addr)
+{
+#if defined(__GNUC__) && \
+ (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+ __clear_cache((char *)addr, (char *)addr + bytes);
+#endif
+}
+
#ifdef DEBUG
// handy function for use in gdb, because Bdescr() is inlined.
There may be further problems; this is as far as I got. In practice, I
don't think I've seen any non-trivial GHCi code working on ARM.
--
Colin Watson [cjwatson@debian.org]
Reply to: