RE: adding isWHNF primop to 5.00.2 native code generator

| Sigbjorn gave me this suggestion, which is based on DataToTagOp. | | \begin{code} | primCode [res] IsHNF [arg] | = let res' = amodeToStix res | arg' = amodeToStix arg | arg_info = StInd PtrRep arg' | word_32 = StInd WordRep (StIndex PtrRep | arg_info (StInt (-1))) | masked_le32 = StPrim SrlOp [word_32, StInt 16] | masked_be32 = StPrim AndOp [word_32, StInt 65535] | #ifdef WORDS_BIGENDIAN | ty_info = masked_le32 | #else | ty_info = masked_be32 | #endif | not_a_thunk = StPrim IntEqOp [ StPrim AndOp [ty_info, StInt 0x10] | , StInt 0x0 | ] | -- ToDo: don't hardwire the value of | _THUNK from InfoTables.h | assign = StAssign IntRep res' not_a_thunk | in | returnUs (\ xs -> assign : xs) | \end{code} | | | I get different results with the version using the C macro | and the native code version. In particular I get the wrong | (unexpected result from the native code version). | | The C macro version works like this (uses these macros): | | #define closureFlags(c) (closure_flags[get_itbl(c)->type]) | -- in ghc/includes/InfoTables.h | | #define closure_THUNK(c) ( closureFlags(c) & _THU) | -- in ghc/includes/InfoTables.h | | #define get_itbl(c) (INFO_PTR_TO_STRUCT((c)->header.info)) | -- in ghc/includes/ClosureMacros.h | | #define INFO_PTR_TO_STRUCT(info) ((StgInfoTable *)(info) - 1) | -- in ghc/includes/ClosureMacros. | | The (-1) scares me a little bit, in INFO_PTR_TO_STRUCT. | | The array closure_flags[] is just a look up table, indexed by | the closure type. So the key part of the code above is: | | get_itbl(c)->type | | In the native code version above, the lines below act like | get_itbl(c): | | arg_info = StInd PtrRep arg' | word_32 = StInd WordRep (StIndex PtrRep arg_info (StInt (-1))) | | After this I am lost. It seems to be grabbing the top or | bottom 16 bits of word_32 (depending on endianness) and then | ANDing those bits with 0x10 (which is the bit mask for _THU), | and checking for 0. | | My feeling is that I should be finding out the "type" field | from the closure and then switching on its value. What you have started with looks plausible. If you can extract enough info from the NCG, you can usually find the problem without too much difficulty. I suggest you make friends with -ddump-stix, so that you can see directly the result of your extension to the primCode fn above. Then (if you are mad enough) the usual way to go about this is: 1. Write a plausible primCode case -- as you've already done. 2. Compile with -ddump-stix and see if it looks plausible in context. 3. Read the assembly code (-ddump-asm) and relate it to the Stix. 4. Try and relate (3) to the assembly code for the same when compiled with -fvia-C. This usually helps. (3) and (4) are a lot easier if you do it on x86 than sparc because x86 code is a lot less verbose. You do need to be clear about x86 addressing modes, tho. | I don't understand the native code generator well enough. I | am assuming that closures are laid out the same way as via-C, Yes. Code from the NCG and -fvia-C is 100% interoperable. | in particular that there is going to be some stuff in the | info table before the "type" field (this looks variable | depending on how things are built). Basically I'm looking for | a way to do the equivalent of "->type". Maybe there is a | better way to do it. Suggestion: find some other primop which uses the ->type field and which is implemented in the NCG (not all are). That might help. Finally let me point you at ghc/utils/debugNCG, a small but very useful program for debugging the NCG. I would never have got it working as well as it does without it. This should work -- but it might have slight bitrot -- it's very fragile and makes lots of assumptions about gcc's output. I haven't used it for a good few months. J
participants (1)
-
Julian Seward (Intl Vendor)