Spin2Cpp (or maybe PropGCC) questions
Rayman
Posts: 14,665
First, let me say that Spin2Cpp is amazing and wonderful.
But, of course, I have to look the gift horse in the mouth a bit...
I'm trying to clean up the code to look more like something I would have wrote myself...
But, there are a few things I don't understand in there...
First, can you remind me why we are using "int32_t" and not just "int".
I was looking at the GNU C Reference manual data types and "int" looks right...
http://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Primitive-Types
Both P1 and P2 are 32-bit, so why create our own type here?
The hello.c example uses just "int"
The fft_bench.c example does this:
Next question is about Yield.
My simple SPIN "repeat" was turned into a loop containing "Yield()".
Having a yield function would make sense if we were doing some kind of multitasking...
Do I really need that there if I just want the program to spin it's wheels indefinitely?
The top of the code has this:
What in the world does that first define do?
Does the second define just mean that Yield is replaced by nothing?
Lastly (for now), what is this all about?:
Actually, do have one more question (sorry):
I can build and run the output using either "propeller-elf-c++" or "propeller-elf-gcc".
My understanding is that the first one is for C++ code and the second one for C code.
Spin2Cpp implied to me that the output was C++ code. But, I think I remember that this is only when you have assembly drivers included.
Is that right? Can SPIN only code sent through Spin2Cpp always be used both ways?
But, of course, I have to look the gift horse in the mouth a bit...
I'm trying to clean up the code to look more like something I would have wrote myself...
But, there are a few things I don't understand in there...
First, can you remind me why we are using "int32_t" and not just "int".
I was looking at the GNU C Reference manual data types and "int" looks right...
http://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Primitive-Types
Both P1 and P2 are 32-bit, so why create our own type here?
The hello.c example uses just "int"
The fft_bench.c example does this:
#define int32_t int#define int16_t short intAgain, this only makes sense to me if we thought we might want to define int32_t to be something else, which I don't see happening...
Next question is about Yield.
My simple SPIN "repeat" was turned into a loop containing "Yield()".
Having a yield function would make sense if we were doing some kind of multitasking...
Do I really need that there if I just want the program to spin it's wheels indefinitely?
The top of the code has this:
#ifdef __GNUC__ #define Yield__() __asm__ volatile( "" ::: "memory" ) #else #define Yield__()I'm very unclear on this part... When is __GNUC__ defined?
What in the world does that first define do?
Does the second define just mean that Yield is replaced by nothing?
Lastly (for now), what is this all about?:
#ifdef __GNUC__ #define PostEffect__(X, Y) __extension__({ int32_t tmp__ = (X); (X) = (Y); tmp__; }) #else #define PostEffect__(X, Y) (tmp__ = (X), (X) = (Y), tmp__)Code seems to work with this commented out... When is it needed?
Actually, do have one more question (sorry):
I can build and run the output using either "propeller-elf-c++" or "propeller-elf-gcc".
My understanding is that the first one is for C++ code and the second one for C code.
Spin2Cpp implied to me that the output was C++ code. But, I think I remember that this is only when you have assembly drivers included.
Is that right? Can SPIN only code sent through Spin2Cpp always be used both ways?
Comments
"int32_t" is the C99 standard way of specifying a 32 bit integer (see the header file <stdint.h>). It will work on any platform, and will work on future 64 bit Propellers. As it happens "int" is 32 bits on PropGCC, but not on the 64 bit Linux where I've been doing my development.
Empty repeat loops are often used to wait for hardware or another COG to do something. The GCC optimizer can be pretty aggressive about moving and deleting code, so I put the call to Yield() in to prevent it from moving anything past the loop. The __asm__ volatile with "memory" as a clobber indicates that any memory might change during the loop, and again is to keep the optimizer from making assumptions. It won't actually add any code, it's just a note to the compiler that the outside world may be doing things that we don't know about. In pure C code you'd normally mark variables as "volatile" for this, but spin2cpp isn't able to do enough analysis to tell which variables might be variable.
It's always defined by the GNU C compiler, and expands to the GCC version number. Most compilers have those kinds of defines, so you can write code that can take advantage of compiler specific features. I think Visual C defines __MSV_VER for a similar purpose. PropGCC defines a bunch of things (see the manual for a list of all of them); some of the interesting Propeller specific ones are: It's used for compiling some Spin expressions that modify a variable but return the original value (like "X^^"). If you don't use those expressions, it won't be needed.
propeller-elf-gcc and propeller-elf-g++ both can compile C or C++ code (they use the file extension to tell which is which). The difference comes in the final link step: g++ includes the standard C++ libraries, and gcc does not. For spin2cpp generated code, which does not use any C++ libraries, it doesn't matter.
Eric
For me, this is not a problem because Windows can run 32-bit code with 64-bit OS just fine.
So, I think maybe I'll be able to build and run with Visual Studio using plain "int".
Also, I think it will be a very, very long time until there's a 64-bit Propeller...
I'm not sure what I'll do about the yield. Think I'll try just deleting it and see if the optimizer punishes me...
I'm not clear on the posteffect part. Doesn't C++ handle things like "x++" the same way as Spin?
I do have a "dira[11]~~ " in there, which is post-set, but it just get's turned into:
DIRA = ((DIRA & 0xfffff7ff) | 0x800);
so, I guess I'll have to try "X^^" and see what that gets turned into.
What's different between 32- and 64-bit platforms is the size of 'long', which is defined to be the size of a pointer: 4 bytes on 32-bit platforms, 8 bytes on 64-bit platforms (the notable exception here is Windows 64, which makes it a troublesome platform). 'long long' is, under the same agreement, defined to be 64 bits on 32- as well as 64-bit platforms.
Maybe you were thinking about 'long'?
-Tor
Why not leave it in? It won't hurt anything.
For things that they both have, yes. But as you've pointed out, there are operators like "~~" that Spin has but C++ doesn't. For example, is translated by spin2cpp into something like: Which sets X to Y+1 and then Y to -1.
If the postfix result is never used (like in your DIRA example) spin2cpp optimizes it away. So you only need the PostEffect__() define if it actually occurs in your source code. The spin2cpp macro generation code isn't quite smart enough to eliminate that, although I probably should fix that.
(And forget my earlier ^^ example, it isn't valid.)
Eric
I was also thinking of other compilers I've used where "int" is certainly not 32 bits (e.g. many microcontrollers).
I think it's a good habit to get into using <stdint.h> whenever a specific size is required, and Spin does expect 32 bit integers.
Thanks,
Eric