On 25/04/2011, at 10:39 AM, Erik de Castro Lopo wrote:
> Erik de Castro Lopo wrote:
>
>> which compiles because C is so lax with types. With the types
>> above the LLVM codegen generates code that is rejected by the
>> LLVM compiler, because the type of _vp1 is incorrect. It should
>> really be void* instead of Obj**.
>
> Compiling a simple file containing just this:
>
> data Ptr# a
>
> foreign import "primStore_peekDataRS_payload"
> peekDataRS_payload
> :: forall a b. a -> Ptr# b
>
> results in an interface file containing:
>
> data Ptr# a;
>
> foreign import "primStore_peekDataRS_payload" peekDataRS_payload
> :: forall a b
> . a -> Ptr# b
> :$ Obj -> Ptr# Obj;
>
> It seems like ddc infers any generic type to be of type Obj.
> That is not unreasonable for boxed values, but in this instance
> seems somewhat off.
Yes.
> The actual use of this I'm looking at is this:
>
> boxInt32 :: Int32# -> Int32
> boxInt32 u
> = do w = primAlloc_dataRS 0# 4#
> poke (coercePtr (peekDataRS_payload w)) u
> w
>
> Expanding it out:
>
> = do w = primAlloc_dataRS 0# 4#
> p1 = peekDataRS_payload w
> p2 = coercePtr p1
> poke p2 u
> w
>
> It then occured to me that, if the compiler internals had more
> info about the stucture of the DataRS object the compiler should
> be able to infer that p1 is in fact a Int32* and the pointer
> coercion would not be needed. The types for peekDataRS_payload
> would then be inferred as:
>
> foreign import "primStore_peekDataRS_payload" peekDataRS_payload
> :: forall a b
> . a -> Ptr# b
> :$ Obj -> Ptr# b;
>
> and we could then write:
>
> boxInt32 :: Int32# -> Int32
> boxInt32 u
> = do w = primAlloc_dataRS 0# 4#
> p = peekDataRS_payload w
> poke p u
> w
>
> Doing this may mean that it is still possible to write low level
> code, including peeks and pokes in disciple but that there is no
> need to use coercePtr at all.
>
> I also think that this may have uses when it comes to doing automatic
> unboxing as and optimisation.
>
> What do you think? Is this an avenue worth pursuing?
The RS stands for "Raw Small". A DataRS object can contain raw data of any
length. By "raw", I mean values that are not pointers that the GC needs to
worry about.
The base libraries can store whatever data they want in an DataRS, so the
internal structure of a DataRS is not something the compiler can generally
infer. For example, we could represent complex numbers by storing two unboxed
doubles in a DataRS, and the compiler won't know anything about that.
I think we'll still need coercePtr for now as it's the base library code itself
that defines the layout of these objects. The "right way" of fixing it would be
to follow GHC's approach, where we can define data constructors that have
unboxed fields.
The operator that returns the unboxed value from within an object would then be
a language primitive, and not a hacky function like peekDataRS_payload. In GHC
they use a case expression:
case boxedThing of
I# unboxedThing -> .... unboxedThing ...
That approach has its own problems though.
In the long term i'd hope to be able to define data constructors with unboxed
fields then use the projection mechanism to access the fields:
data Int
= Int { unboxed :: Int# }
boxedX = 5
unboxedX = boxedX.unboxed
The point here is that the compiler can work out that boxedX has type Int, and
it knows what the internal structure of that is. In contrast, all
peekDataRS_payload knows is that it's been passed an object of type "a", which
could be anything.
Ben.
--
Disciple-Cafe mailing list
http://groups.google.com/group/disciple-cafe