Callback function - Can't generate code for this expression

Thread Starter

spinnaker

Joined Oct 29, 2009
7,830
Not sure if this belongs in the Programmers Corner or here. But since it is the XC8 compiler I figured I would put it here.

I am getting a Can't generate code for this expression in the following code:

Rich (BB code):
typedef  void (*OW_update_cb)(unsigned int count);

void foo(OW_update_cb update_cb)
{

     update_cb(0);  // Error occurs here
}
If I make my return type an int then everything compiles OK. Or if I do not have any parameters and a void return type for the callback function then it compiles.

This compiles with the corresponding correction to the call to the callback.
typedef void (*OW_update_cb)();


This also compiles just fine.
typedef int (*OW_update_cb)(unsigned int count);


Any idea what is going on? I have not used callback functions all that much.
 

JohnInTX

Joined Jun 26, 2012
4,787
That's the way I've done it (in HiTech C) as well. But I moved the '*' outside the parenthesis
Rich (BB code):
typedef void *(OW_update_cb) (unsigned int count);
and it compiles. Don't know if it generates the code you want.

Good luck.

EDIT XC8 1.21 FREE mode
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,830
Thanks

This worked for some reason.
typedef void *(OW_update_cb)(unsigned int count);

The only thing, the editor complains "Unable to resolve identifier count" but it compiles.

I'll test tomorrow to see if the code actually works. Time for bed now. :)


This is the last project I am going to be doing in XC8 for a while. I am switching back to MPLab. I never had more trouble with a compiler, all kind of issues.
 

JohnInTX

Joined Jun 26, 2012
4,787
Thanks

This worked for some reason.
typedef void *(OW_update_cb)(unsigned int count);

The only thing, the editor complains "Unable to resolve identifier count" but it compiles.

I'll test tomorrow to see if the code actually works. Time for bed now. :)

This is the last project I am going to be doing in XC8 for a while. I am switching back to MPLab. I never had more trouble with a compiler, all kind of issues.
It should work as you wrote it. Here's a little gem from XC8 Compiler Help:
How Do I Fix a “Can’t generate code...” Error?​
This is a catch-all message which is generated if the compiler has exhausted all possible means of compiling a C expression, see “Error and Warning Messages”. It does not usually indicate a fault in your code. The inability to compile the code can be a deficiency in the compiler, or an expression that requires more registers or resources than are available at that point in the code. This is more likely to occur on baseline devices. In any case, simplifying the offending expression, or splitting a statement into several smaller statements, usually allows the compilation to continue. You can need to use another variable to hold the intermediate results of complicated expressions.
Boldface added.

EDIT It didn't seem to generate ANY code for the callback fragment you posted, even when changing the type to int(*) without calling 'foo'. When 'foo' is called, it looks like it correctly pushes the address contained in the pointer-to-function variable update_cb on the stack and do a 'return' to call the function. It also accepted the original typedef syntax.

This is the last project I am going to be doing in XC8 for a while. I am switching back to MPLab. I never had more trouble with a compiler, all kind of issues.
Yeah.. kind of agree with you there. I keep trying it for various things and run across this kind of stuff as well.

If you think its a compiler issue, send a gripe to Microchip support. They may have a workaround or at least put it on the 'issues' list.

EDIT EDIT:
This generates code and gets to 'bar':
Rich (BB code):
#include <xc.h>
typedef  void(*OW_update_cb)(unsigned int);

void bar(){
    unsigned char i;
    for(i=0;i<10;i++); // give it something to do so it doesn't get optimised out
}

void foo(OW_update_cb update_cb)
{
    update_cb(0);  // Error occurs here
}

void main() 
{
   while (1){
      foo((OW_update_cb)bar);
   }
}
Here's the generated code:
Rich (BB code):
            #include <xc.h>
9:             typedef  void(*OW_update_cb)(unsigned int);
10:            
11:            void bar(){
12:                unsigned char i;
13:                for(i=0;i<10;i++); // give it something to do so it doesn't get optimised out
7FCA  6E03     MOVWF 0x3, ACCESS
7FCC  0E00     MOVLW 0x0
7FCE  6E04     MOVWF i, ACCESS
7FD0  5003     MOVF 0x3, W, ACCESS
7FD2  D001     BRA 0x7FD6
7FD4  2A04     INCF i, F, ACCESS
7FD6  0E09     MOVLW 0x9
7FD8  6404     CPFSGT i, ACCESS
7FDA  D7FC     BRA 0x7FD4
14:            }
7FDC  0012     RETURN 0
15:            
16:            void foo(OW_update_cb update_cb)
17:            {
18:                update_cb(0);  // Error occurs here
;;Put 0 param into registers 01h,02h
7FDE  0E00     MOVLW 0x0
7FE0  6E02     MOVWF 0x2, ACCESS
7FE2  0E00     MOVLW 0x0
7FE4  6E01     MOVWF 0x1, ACCESS
7FE6  D801     RCALL 0x7FEA
7FE8  D00A     BRA 0x7FFE
;; Push stack, put contents of update_cb (&bar) on TOPSTK
7FEA  0005     PUSH
7FEC  6EFA     MOVWF PCLATH, ACCESS
7FEE  5005     MOVF update_cb, W, ACCESS
7FF0  6EFD     MOVWF TOSL, ACCESS
7FF2  5006     MOVF 0x6, W, ACCESS
7FF4  6EFE     MOVWF TOSH, ACCESS
7FF6  50F8     MOVF TBLPTRU, W, ACCESS
7FF8  6EFF     MOVWF TOSU, ACCESS
7FFA  50FA     MOVF PCLATH, W, ACCESS
;; POP address of 'bar' into PC to call it
7FFC  0012     RETURN 0
19:            }
20:            
21:            void main() 
22:            {
23:               while (1){
24:                  foo((OW_update_cb)bar);
;; This puts the address of 'bar' (7FCA) into update_cb
7FBC  0E7F     MOVLW 0x7F  
7FBE  6E06     MOVWF 0x6, ACCESS
7FC0  0ECA     MOVLW 0xCA
7FC2  6E05     MOVWF update_cb, ACCESS
7FC4  ECEF     CALL 0x7FDE, 0
7FC6  F03F     NOP
7FC8  D7F9     BRA main
25:               }
26:            }
Last EDIT - bed for me as well :)
The only thing, the editor complains "Unable to resolve identifier count" but it compiles.
That's common and I don't know why it is exactly. It will also flag some library functions/macros delay macros as unresolved but they compile correctly as well. Its still pretty handy to the extent that it does work.
 
Last edited:

nsaspook

Joined Aug 27, 2009
13,279
Still waiting for XC8 to be a good bare-metal compiler in 'lite mode' but upgrade to 1.30 to see if that helps. C18 might be slow and simple but it usually generates usable (lacking optimization but not artificially bloated) code in the LITE mode and can still be used in MPLABX if you change the project compiler setting.

My first opinion of XC8 hasn't change much over the years.
https://forum.allaboutcircuits.com/showpost.php?p=535972&postcount=23
 
Last edited:
Top