flexprop icon indicating copy to clipboard operation
flexprop copied to clipboard

I'm not sure if this is a bug...

Open jrullan opened this issue 2 years ago • 5 comments

Thanks for fixing all the bugs related to method pointers in Spin2.

During my testing of 5.9.21 I ran into the following issue:

image

My understading is that method_pointers[0] contains an address that refers to a hub memory location, and that hub memory is 8 bits wide. That is why in Propeller Tool I use LONG[method_pointers][0] to make sure to access all 32 bits of the method pointer. In Propeller Tool if I dont use LONG[] it does not recognize the return address as a method pointer.

However in FlexProp

LONG[method_pointers][0](1,2)

does not work and the syntax

method_pointers[0](1,2)

does.

jrullan avatar Dec 08 '22 00:12 jrullan

method_pointers is declared as a LONG variable in the VAR section, so there should be no need to use LONG[method_pointers] in either compiler. On the other hand it should probably work, so I'll look into it.

When you say "in Propeller Tool if I don't use LONG it does not recognize the return address as a method pointer" what error does Propeller Tool produce? And by "return address" do you mean the expression method_pointers[0]?

totalspectrum avatar Dec 08 '22 12:12 totalspectrum

Actually no, looking at this in more detail, LONG[method_pointers][0] is not at all the same as method_pointers[0]. The first one adds an additional level of indirection, that is, it fetches the value stored at method_pointers, and then the LONG[] fetches the value stored in memory there. That isn't expected to work. I don't understand why it would in PNut.

I just tried with PNut v37, and the following program does what I would expect:

CON
  _clkfreq = 160_000_000
VAR
  long methods[3]
  long method_pointers[3]

PUB main()|f
  init()

  method_pointers[0] := methods[0]
  debug(uhex(methods[0]), uhex(long[methods][0]))
  function1(1, 0)
  methods[0](1, 1)
  method_pointers[0](1, 2)
  
  function2(2, 0)
  methods[1](2, 1)

  function3(3, 0)
  methods[2](3, 1)


PUB init()
  methods[0] := @function1
  methods[1] := @function2
  methods[2] := @function3

PUB function1(a, b) : val
  val := 1
  DEBUG(udec(val), udec(b))

PUB function2(a, b) : val
  val := 2
  DEBUG(udec(val), udec(b))

PUB function3(a, b) : val
  val := 3
  DEBUG(udec(val), udec(b))

So you should never use LONG[method_pointers][0].

totalspectrum avatar Dec 08 '22 21:12 totalspectrum

Ha! I did not test that. However my use case scenario is the following (using Propeller Tool):

Main application object that has two objects:

  1. Services Object - Contains methods common to all other objects
  2. Child Object - Object that uses the services provided by the Services object of the parent

Note: This test code is an over simplification of my use case. I have 10+ child objects that all use the methods provided by a service object wrapped by the parent object. But this illustrates the issue with the syntax.

''Main application object
CON
  _clkfreq = 200_000_000

OBJ
  services   : "test_services_obj"
  child      : "test_method_pointer_obj"

VAR
  LONG methods[3]

PUB main()|f
  init()

  ''This works at this level
  methods[0]()


  ''But when invoking them in a child object...
  ''(see comments in test_method_pointer_obj)

  'Pass pointer to child object
  child.set_methods_pointer(@methods)

  'Now invoke one of the service methods from the child
  child.call_service_method(0)


PUB init()
  methods[0] := @services.method1
  methods[1] := @services.method2
  methods[2] := @services.method3

The services object:

''Services object
PUB null()

PUB method1():r
  r := 1
  debug(udec(r))

PUB method2():r
  r := 2
  debug(udec(r))

PUB method3():r
  r := 3
  debug(udec(r))

and the child object

''Child object
VAR
  LONG methods_pointer


PUB set_methods_pointer(ptr)
  methods_pointer := ptr


PUB call_service_method(m)
  debug("services method ", udec(m))

  'This crashes
  ' methods_pointer[m]()

  'This does not crash
  LONG[methods_pointer][m]()

The syntax you point out works at the main object level, however when calling them from another child it seems to require the LONG[] syntax.

In FlexProp, calling methods_pointer[m]() in the child object does not work, but it doesn't crash. However trying to call LONG[methods_pointer[m]() throws an error.

jrullan avatar Dec 09 '22 02:12 jrullan

Ah, I see. I'll try to fix this. For now you can work around it with:

PUB call_service_method(m) | f
  f := LONG[methods_pointer][m];
  f()

totalspectrum avatar Dec 09 '22 12:12 totalspectrum

Great! I will probably be able to port my project to FlexProp once these method pointers compatibility issues are solved. Thanks.

jrullan avatar Dec 09 '22 13:12 jrullan

This is fixed in flexprop 5.9.22-beta.

totalspectrum avatar Dec 17 '22 18:12 totalspectrum