How to get GCC to evaluate functions at compile time?

I think about the following problem: I want to program a microcontroller (for example, type AVR mega) with a program that uses some kind of lookup tables.

The first attempt would be to find the table in a separate file and create it using any other language / script program / .... In this case, when creating the necessary source files for C.

Now I was thinking of using a preprocessor and compiler to handle things. I tried to implement this using a sine value table (as an example):

#include <avr/io.h> #include <math.h> #define S1(i,n) ((uint8_t) sin(M_PI*(i)/n*255)) #define S4(i,n) S1(i,n), S1(i+1,n), S1(i+2,n), S1(i+3,n) uint8_t lut[] = {S4(0,4)}; void main() { uint8_t val, i; for(i=0; i<4; i++) { val = lut[i]; } } 

If I compile this code, I get warnings about the sin function. Further in the assembly there is nothing in the .data section. If I just delete sin in the third line, I will get the data in the assembly. Obviously, all information is available at compile time.

Can you tell me if there is a way to achieve what I intend: the compiler calculates as many values ​​as possible in offline mode? Or is this the best way to use an external script / program / ... to calculate the entries in the table and add them to a separate file, which will simply be #include d?

+5
source share
3 answers

A common problem is that calling sin makes this initialization de facto illegal, in accordance with the rules of the C language, since it is not a constant expression per se, and you initialize an array of static storage duration, which requires this. This also explains why your array is not in the .data section.

C11 (N1570) §6.6 / 2,3 Constant expressions (emphasis mine)

The constant expression can be evaluated at the time of translation, not the execution time, and, accordingly, can be used at any place where the constant can be.

Constant expressions must not contain assignment, increment, decrement, function call or commas, unless they are contained in a subexpression that is not evaluated .115)

However, according to a comment by @ShafikYaghmour, GCC will replace the call to the sin function with its built-in counterpart (if the -fno-builtin option is not enabled), which is most likely to be considered a constant expression. According to 6.57 Other built-in functions provided by GCC :

GCC includes embedded versions of many functions in the standard C library. The version with the __builtin_ prefix is ​​always considered to have the same meaning as the C library function, even if you specify the -fno-builtin option.

+4
source

What you are trying is not part of the C language. In such situations, I wrote the code following this pattern:

 #if GENERATE_SOURCECODE int main (void) { ... Code that uses printf to write C code to stdout } #else // Source code generated by the code above ... Here I paste in what the code above generated // The rest of the program #endif 

Every time you need to change it, you run the code with GENERATE_SOURCECODE set and paste it. Works well if your code is autonomous, and the generated output only ever changes if the code generates it.

+2
source

First of all, you need to say that you should evaluate (perhaps by experiment) whether it is worth doing. Your lookup table will increase your data size and programmer work, but may or may not provide the required increase in execution speed.

If you still want to do this, I don’t think the C preprocessor can do this directly because it doesn’t have the ability to iterate or recurse.

The most reliable way to do this is to write a C program or some other language to print the C source code for this table, and then include this file in your program using a preprocessor. If you use a tool such as make , you can create a rule to create the table file and associate the .c file with this file.

On the other hand, if you are sure that you are never going to change this table, you can write a program to create it once and just insert it.

+2
source

Source: https://habr.com/ru/post/1211711/


All Articles