|
|
View previous topic :: View next topic |
Author |
Message |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
Macro expansion problem |
Posted: Thu Apr 22, 2004 2:21 pm |
|
|
I think I found a compiler bug related to macro expansions. Sometimes two assembly lines are missing in the expanded code, this depends on the context and sequence of the macro being used.
I'm using PCH v3.187 on a PIC18F458.
In the following code:
Code: |
#include <18F458.h>
#use delay(clock=16000000)
#fuses HS,NOWDT,OSCSEN,PUT,BROWNOUT,NOLVP
int IsLeap() {return TRUE;}
#define YEAR_SIZE(year) (IsLeap() ? 366 : 365)
void main()
{
int16 foo=0;
foo >= YEAR_SIZE(1000); // Error
foo <= YEAR_SIZE(1000); // Error
foo == YEAR_SIZE(1000); // Error
foo = YEAR_SIZE(1000); // OK
foo += YEAR_SIZE(1000); // OK
foo -= YEAR_SIZE(1000); // OK
// And now the funny part
// with the same code again.
foo >= YEAR_SIZE(1000); // OK !!!!
foo <= YEAR_SIZE(1000); // OK !!!!
foo == YEAR_SIZE(1000); // OK !!!!
foo = YEAR_SIZE(1000); // OK
foo += YEAR_SIZE(1000); // OK
foo -= YEAR_SIZE(1000); // OK
}
|
Studying the assembly code for the error lines, there are two missing instructions compared to the correct lines:
Code: |
18: foo >= YEAR_SIZE(1000); // Error
000024 EC02 CALL 0x4, 0
000028 5201 MOVF 0x1, F, ACCESS
00002A B4D8 BTFSC 0xfd8, 0x2, ACCESS
00002C EF1B GOTO 0x36
-- Missing for the error examples !!! -------
MOVLW 0x1
MOVWF 0x3, ACCESS
-------------------------------------------------
000030 0E6E MOVLW 0x6e
000032 EF1E GOTO 0x3c
000036 0E01 MOVLW 0x1
000038 6E03 MOVWF 0x3, ACCESS
00003A 0E6D MOVLW 0x6d
00003C 6E01 MOVWF 0x1, ACCESS
00003E 5003 MOVF 0x3, W, ACCESS
000040 5C07 SUBWF 0x7, W, ACCESS
000042 A0D8 BTFSS 0xfd8, 0, ACCESS
000044 EF2C GOTO 0x58
000048 A4D8 BTFSS 0xfd8, 0x2, ACCESS
00004A EF2F GOTO 0x5e
00004E 5001 MOVF 0x1, W, ACCESS
000050 5C06 SUBWF 0x6, W, ACCESS
000052 B0D8 BTFSC 0xfd8, 0, ACCESS
000054 EF2F GOTO 0x5e
000058 0E00 MOVLW 0
00005A EF2F GOTO 0x5e
19: foo <= YEAR_SIZE(1000); // Error
|
The bug(?) only occurs for the macro's used in combination with an equation (==, <=, >=). The strange thing is that after once having used the macro in combination with an assignment (=, +=, -=) all macro's are expanding correctly.... Looks like an compiler initialization problem????
Can someone explain to me if I'm overlooking something or should I report this as a bug?
Last edited by ckielstra on Fri Apr 23, 2004 2:28 am; edited 1 time in total |
|
|
RKnapp
Joined: 23 Feb 2004 Posts: 51
|
|
Posted: Thu Apr 22, 2004 7:29 pm |
|
|
ckielstra,
I am using PCH 3.187 (I reverted back from 3.190) on 18F8720 and have also had macro expansion problems, specifically with the ? : operator.
I am willing to admit that there is some kind of bug below that precludes these from compiling correctly, but I don't see it. These don't COMPILE, so I don't know if this is related to what you're seeing or not:
Code: |
#define _TOGGLE(flag) {if(flag==TRUE) flag=FALSE; else flag=TRUE;}
// Note, for unknown reasons, these do not work:
//#define _TOGGLE(flag) {(flag==TRUE)?{flag=FALSE;}:{flag=TRUE;};}
//#define _TOGGLE(flag) (flag ? flag=0 : flag=1)
|
I would really like to know what you find out!
Have a good day,
Robert |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Apr 23, 2004 1:45 am |
|
|
Hi Robert,
Your problem is quiet different from mine. You get compiler error messages because of grammatical errors in your code, where my program does compile without warnings but has an error in the resulting assembly code.
Comming back to your problem:
Be aware that there is a huge difference between the '?:' and the 'if-then' constructions. The first one is an operator and the second one a statement, you can not exchange these two at will. You can only use the ?: operator in situations where you normally would write a value.
Only use the ?: operator where it has a real advantage because it often makes your code harder to read, where possible use the if-then statement. I even worked for some companies that didn't allow the use of the ?: operator.
If you do insist on using the ?: operator you could have written your code like this:
Code: |
#define _TOGGLE1(flag) (flag ? (flag=0) : (flag=1))
#define _TOGGLE2(flag) (flag==TRUE)?(flag=FALSE):(flag=TRUE)
#define _TOGGLE3(flag) (flag ? 0 : 1)
#define _TOGGLE(flag) {if (flag==TRUE) flag=FALSE; else flag=TRUE;}
void main()
{
int8 flag=0;
_TOGGLE1(flag); // 20 bytes
_TOGGLE2(flag); // 18 bytes
flag = _TOGGLE3(flag); // 18 bytes
_TOGGLE(flag); // 16 bytes
}
|
But, as said, I prefer the if-then implementation which also turns out to result in the shortest code here.
Carlo
Last edited by ckielstra on Fri Apr 23, 2004 2:05 am; edited 1 time in total |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Fri Apr 23, 2004 2:01 am |
|
|
According to the version history page at:
http://www.ccsinfo.com/versions.shtml
3.189 Macro processing algorithm has been updated to meet ANSI requirements
This might be related to what you are seeing in 3.187. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Apr 23, 2004 2:32 am |
|
|
Version 3.187 is the latest version I have. Is there someone who can check my bug being fixed by the change in v3.189? The release note only mentions a change to meet the ANSI requirements, nothing about bug fixes.... |
|
|
RKnapp
Joined: 23 Feb 2004 Posts: 51
|
|
Posted: Fri Apr 23, 2004 1:46 pm |
|
|
ckielstra,
You have some good advice there for me. You can see that I wanted the toggle to not just fork over a true / false but actually alter the variable fed to it.
But based on your comments I'm more content with the if/then/else structure.
Thanks,
Robert
ps. In past code I've used the ? : operator to deliver strings, e.g.:
Code: |
#define _SHOW_fGPS_Status(flag)\
((flag==GPS_NO_INPUT_RS232_) ? "(GPS_NO_INPUT_RS232_)" : \
(flag==GPS_BAD_SAT_COVERAG) ? "(GPS_BAD_SAT_COVERAG)" : \
(flag==GPS_SIMULATED_INPUT) ? "(GPS_SIMULATED_INPUT)" : \
(flag==GPS_DATA_SANITY_ERR) ? "(GPS_DATA_SANITY_ERR)" : \
(flag==GPS_SPEED_L_BOUNDED) ? "(GPS_SPEED_L_BOUNDED)" : \
(flag==GPS_SPEED_LT_1_KNOT) ? "(GPS_SPEED_LT_1_KNOT)" : \
(flag==GPS_SPEED_NORML_RNG) ? "(GPS_SPEED_NORML_RNG)" : \
(flag==GPS_SPEED_U_BOUNDED) ? "(GPS_SPEED_U_BOUNDED)" : \
"(CALL ROBERT KNAPP!) " )
|
My questions to you or anyone are:
a) where are strings like this stored? Do they take up RAM or go into ROM?
b) (I've noticed that some of my printf() stmts have tons of code so I'm wondering where their strings are stored, too.)
c) And, if I have such macros defined in a header file but do not invoke them in my code, are they tossed on the floor, or are they stuffed into RAM, too? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Apr 26, 2004 8:05 am |
|
|
a) Constant values/strings are always stored in ROM, where else are they to stay when you remove the power? When assigned to a variable, for example when initializing, the compiler might copy the value to RAM also.
b) Printf statements are known to be huge, especially the ones with difficult format-strings. Their (format)strings are constants, so stored in ROM too.
c) Any good compiler would ignore unused defines, so no storage usage. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|