[FlexSpin] Filling structs from function calls
Hey @ersmith
Does the attached look like it could be a bug? I'm trying to populate a structure using the return from a function. I'm not in the habit of returning instances of structures, but the one I've defined is the same overall size as a long, so I though it may work. The symptom I'm seeing is it doesn't seem to fully write (only the last byte seems to make it in, shown by the debug hexdump). Weirdly, if I add a second debug statement to the function that's populating the structure, it works correctly. NuCode also works correctly here (without the need for uncommenting that second hexdump).
As an alternative, returning a pointer to the same type of structure instead works better with one call, although if I make two separate calls to two different structs, only the second one seems to get written, so it seems like something isn't quite right there, either.
Thanks

Comments
@avsa242 Yes, that certainly looks like a bug. I can't quite see the root cause, though. At first I thought it was an optimization issue, but it still happens with
-O0.For now, I would recommend avoiding returning structs, or at least structs that need packing (i.e. that contain words or bytes). I think unpacked structs will probably work, or at least are better tested.
Thanks for looking into it! Will do...that seems the easiest way to workaround.
@avsa242 I think I found the root cause -- variables declared as return values are handled slightly differently than ordinary local variables, and we were missing a check for return values in some places. I have a fix for this (checked in to github) and will make a new release soon. In the meantime, a work-around is to not use the return variable directly, but instead declare a local variable with that structure type and do all assignments to that:
@ersmith
Thanks! Confirmed the direct passing works now. Any ideas on the second case in that code (the indirect one that's commented out)?
The second (indirect) case is rather broken in the original source, I'm afraid. Actually even the original example has a bug:
bytefill(@pstr1, 0, 132)writes to undefined memory, because@pstr1has never been initialized. If you wanted to take the address of the actual reference pointer you'd need an expression like@[pstr1]The thing to remember is that pointers in Spin2 work backwards from how they do in most other languages. That is, in Spin2 if a variable is declared like
.
^teststruct pstr1. then writing justpstr1creates a dereference (like*pstr1in C), and in order to get or set the underlying 32 bit pointer you have to use[pstr1]. I think this is an unfortunate language decision, but I didn't design itIn order to use a pointer, the underlying variable has to be initialized first with a statement like
[pstr1] := @real_str1. This happens implicitly for parameters, so using pointer parameters is actually quite convenient, but for local variables and even more so for return values it needs to be explicit. Actually returning a pointer to a struct is probably a bad idea, because unless you're careful you'll end up with a dangling pointer.My rule of thumb would be to only ever use
^teststructon parameters; for everything else use plainteststruct(without the pointer indicator^).