Shop OBEX P1 Docs P2 Docs Learn Events
Compiler bug? — Parallax Forums

Compiler bug?

mparkmpark Posts: 1,305
edited 2008-08-09 18:08 in Propeller 1
Can anyone explain why this program prints "666 666" instead of "1234 666" as I expected?
I thought bug0._1234 would call bug1._1234 which would return 1234, not 666. Am I wrong?

Looking at the bytecode I see two copies of the "bug2" object and no "bug0" objects, so the
bug0._1234 call actually ends up being a call to bug2._666. It seems to me that the compiler,
in its zeal to eliminate duplicate objects, has mistakenly determined that "bug0" and "bug2"
are the same. However, the last time I suspected a compiler bug, I was wrong, so I'm not
even going to bring up the possibility of the compiler being at fault here.

I've attached a project archive.

' buggy.spin
CON
  _clkmode = xtal2 + pll8x      ' Enable external clock range 5-10MHz and pll times 8.
  _xinfreq = 10_000_000 + 0000  ' Set frequency to 10 MHz.
OBJ
  term : "pc_text"
  bug0 : "bug0"
  bug2 : "bug2"
PUB Start
  term.start(12)
  [b]term.dec( bug0._1234 ) '<== Expected 1234, got 666[/b]
  term.out( " " )
  term.dec( bug2._666 )



' bug0.spin
OBJ
  bug_ : "bug1"
  bug1 : "bug1"
PUB _1234
  return bug1._1234



' bug1.spin
PUB _1234
  return 1234



' bug2.spin
OBJ
  bug3 : "bug3"
  bug4 : "bug4"
PUB _666
  return bug4._666



' bug3.spin
PUB Start
  return 1234



' bug4.spin
OBJ
  bug3 : "bug3"
PUB _666
  return 666

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Michael Park

PS, BTW, and FYI:
To search the forum, use search.parallax.com (do not use the Search button).
Check out the Propeller Wiki: propeller.wikispaces.com/

Comments

  • BradCBradC Posts: 2,601
    edited 2008-08-08 11:34
    Interesting indeed.
    Looking at only the method bytecode, object 0 and 2 are the same. I wonder if the compiler uses some form of hash to perform duplicate reduction and has missed something blindingly obvious ?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pull my finger!
  • Adrian SchneiderAdrian Schneider Posts: 92
    edited 2008-08-08 13:50
    As far as I remember a Parallax-statement about this, only the byte code matters and seems to be identical for bug0 and bug2.
    In reality such a situation would be very unlikely. If you expect such a situation, you may need to make the two module bytecodes
    different explicity, e.g. by adding deffering CON decalarations to both (kind of a module ID).
    Adrian
  • hippyhippy Posts: 1,981
    edited 2008-08-08 14:14
    Ouch; that's a wicked one.

    As BradC says, the bytecode of Bug0 and Bug2 are exactly the same - both are "call the first
    method of the second sub-object - and it does look like the compiler or linker has decided these
    are the same so only one or the other needs to be referenced in the top-level program.

    That suggests that when the compiler or linker is comparing objects to optimise away duplicates,
    it compares only the actual bytecode of the object itself, not how it would be when linked with its
    own sub-objects. However, when I tried different programs which should show the same flaw
    they didn't.

    There seems to be something about this particular code which causes the strange behaviour. I've
    no idea what though.
  • mparkmpark Posts: 1,305
    edited 2008-08-08 20:22
    So it's not me, it really is the compiler behaving badly? Should we report this to someone?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Michael Park

    PS, BTW, and FYI:
    To search the forum, use search.parallax.com (do not use the Search button).
    Check out the Propeller Wiki: propeller.wikispaces.com/
  • Mike GreenMike Green Posts: 23,101
    edited 2008-08-08 22:17
    hippy,
    I believe you've got the explanation. My understanding is that the compiler looks at the generated byte codes, that's all. Admittedly, this is a degenerate example and would be difficult to duplicate with any "real" objects, but it at least needs to be formally documented.
  • hippyhippy Posts: 1,981
    edited 2008-08-08 23:08
    The strange thing is that the following works. The code generated for X1.Spin and X2.Spin is
    exactly the same ( excluding X1sub.Spin and X2sub.Spin ). Something with the way the
    objects are nested in the OP's post must be why that doesn't work.

    ' X.spin
    OBJ x1 : "X1"
    OBJ x2 : "X2"
    PUB Main
      result := x1.Method
      result := x2.Method
    
    ' X1.Spin
    OBJ subObj : "X1sub"
    PUB Method
      return subObj.Method
    
    ' X2.Spin
    OBJ subObj : "X2sub"
    PUB Method
      return subObj.Method
    
    ' X1sub.Spin
    PUB Method
      return 1234
    
    ' X2sub.Spin
    PUB Method
      return 666
    
    
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-08-09 00:52
    It's starting to look like the design intent was correct (i.e. test the subobjects, too) but that there's been a failure in the iteration. In Michael's example the first objects in bug0 and bug2 refer to files that compile to identical bytecodes. It may be that the compiler, upon seeing that, simply stopped testing and decided they were identical, rather than moving on to the next object in each. In Hippy's example, the first objects in X1 and X2 refer to files that don't compile to the same bytecodes, which the compiler apparently recognized.

    One thing seems certain, though: a thorough test could really get messy!

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
  • AleAle Posts: 2,363
    edited 2008-08-09 07:35
    I was thinking if it could be the names of the methods... _1234 and _666, I know it should compare strings! what for a lame suggestion
  • hippyhippy Posts: 1,981
    edited 2008-08-09 14:45
    @ Phil : I tried my example with a number of levels of simple pass-on methods in sub-objects and that still worked okay. I also tried with a number of dummy objects to try and get some 'confusion' in the compiler but that didn't break anything.

    I did try changing the names to _1234 and _666 just in case but no difference.

    Going back to the OP's code, the Pc_Term object can be removed ( using result := instead) and OBJ bug3 : "bug3" in Bug4.spin can also be removed and the problem still remains. That gives an object tree of ...

    Buggy ---.--- Bug0 ---.--- Bug1  (1234)
             |            `--- Bug1  (1234)
             |
             `--- Bug2 ---.--- Bug3  (1234)
                          `--- Bug4  (666)
    
    
    



    That points to a correlation between Bug1 and Bug3 as the trigger. So I then tried this ...

    Buggy ---.--- Bug0 ---.--- BugX  (1234)
             |            `--- Bug1  (1234)
             |
             `--- Bug2 ---.--- BugX  (1234)
                          `--- Bug4  (666)
    
    
    



    That also fails to generate correct code, but only when BugX returns 1234, return 0 and code is okay. Bug4 can also be anything ( other than 1234 when object optimisation would be legit ). Fair enough, Bug1 and BugX are synonymous so one of those two can be optimised, so simplified ...

    Buggy ---.--- Bug0 ---.--- BugX  (1234)
             |            `--- BugX  (1234)
             |
             `--- Bug2 ---.--- BugX  (1234)
                          `--- Bug4  (666)
    
    
    



    That too generates incorrect code, so why are Bug0 and Bug2 considered the same ? The really strange thing is that code for both Bug0 and Bug2 are included in the image, but the call to Bug2 has been replaced by a call to Bug0 in the method link table, so the compiler knows Bug2 hasn't been fully optimised away or it wouldn't include it.

    Looking at the bytecode for just Bug0 and Bug2 method, that's the same no matter what optimisations are done by the compiler in all the testing so it has to be something else which causes the objects to be sometimes be considered synonymous and other times not.

    Post Edited (hippy) : 8/9/2008 3:09:15 PM GMT
  • hippyhippy Posts: 1,981
    edited 2008-08-09 14:56
    Also, just to throw more mystery into the mix, this generates incorrect code ...

    Buggy ---.--- Bug0 ---.--- BugX  (1234)
             |            }--- BugX  (1234)
             |            `--- BugX  (1234) <- Called
             |
             `--- Bug2 ---.--- BugX  (1234)
                          }--- BugX  (1234)
                          `--- Bug4  (666)  <- Called
    
    
    



    This generates correct code ...

    Buggy ---.--- Bug0 ---.--- BugX  (1234)
             |            }--- BugX  (1234) <- Called
             |            `--- BugX  (1234)
             |
             `--- Bug2 ---.--- BugX  (1234)
                          }--- Bug4  (666)  <- Called
                          `--- BugX  (1234)
    
    
    



    Could it simply be that when comparing images for sub-objects when there's more than one the last sub-object isn't being included in the comparison ?

    Post Edited (hippy) : 8/9/2008 3:02:50 PM GMT
  • rokickirokicki Posts: 1,000
    edited 2008-08-09 15:14
    Is this the first actual compiler bug found since the first public release?
    I think some oddities were found before, but I think they were all design intents; I suspect this
    particular case is a legitimate fencepost error.
  • hippyhippy Posts: 1,981
    edited 2008-08-09 16:20
    I'd consider "CogNew( object.method, @stack )" with no error message and not working as would be expected to be a long standing bug which has tripped quite a few up.

    If it were detailed in the manual what that actually did and it did indeed do that I'd accept it as a "trap" rather than a bug.

    Post Edited (hippy) : 8/9/2008 4:26:38 PM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-08-09 16:41
    hippy said...
    Could it simply be that when comparing images for sub-objects when there's more than one the last sub-object isn't being included in the comparison ?
    That sounds reasonable. My hypothesiis (testing first only) and yours (testing all but the last) would be equivalent with two sub objects. Before you posed this, and after I read some of your early counter examples, I was starting to think "hash collision". A strong hash would be a good way to tag objects for comparison purposes. But if the hash is weak, collisions could easily occur, making different objects appear the same. I doubt this is the case here since there are now so many examples of incorrectly-compiled code. But the 0 vs. 1234 thing still makes me wonder...

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
  • hippyhippy Posts: 1,981
    edited 2008-08-09 18:08
    Hmm, that "it only works with 1234 not 0" throws a spanner in the theory that everything matches except the last object. I think we're stuck at going no further than guessing and it's going to take someone in Parallax to drag out the source code and determine exactly what is going on in the compiler.
Sign In or Register to comment.