floating-point and 'pow' function breaks compiler[SOLVED]

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I need to use the power function -- pow(double,double), and I also need floating-point printf support.

However my code won't compile without the dreaded error:

Quote:
relocation truncated to fit: R_AVR_13_PCREL...

I've been happily using 4.5.1 built using Bingo's script for over a year. But after much study and compiling of compilers, I have boiled down the problem. It is identical to this thread from 2011 and some code from the test-suite:
http://lists.gnu.org/archive/html/avr-gcc-list/2011-06/msg00022.html

Further, I found a patch which appeared as if it might fix the error, which led me to recompile my compiler to apply that patch.
http://sourceware.org/bugzilla/show_bug.cgi?id=13410

But after trying the Atmel 4.6.2 compiler, I built combinations of binutils-2.21 and 2.22, with patches, etc. and have found nothing which can compile that code.

The code will compile fine WITHOUT floating point printf support (as long as you use -lm to link the math lib).
But if you use

Quote:
-Wl,-u,vfprintf -lprintf_flt -lm
on the command line, it fails.

Anyone have a compiler that can accomplish this task?

Last Edited: Sun. Feb 3, 2013 - 04:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This sounds very unlikely.

The obvious workaround is to use dtostrf() to format your f-p expressions, and use the regular printf().

Once you have your app working, you can experiment with printf_flt(). And post a buildable example that illustrates your problem. (quote your tool versions)

Others can attempt to replicate your results.
This may narrow it down to the tool, build, O.S. time of the month etc.

We can then post a 'documented' bug to the official GCC supremos.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually my app is working by dual sqrt calls to get a 4th root. Then printf works fine to show me the results. I'm just hoping not to need a cube root!

The failing example in the above link can easily be tested with the addition of a printf call, but since it won't compile there is little point.

It was the combination of a pow(n, .25) call and a following printf that started this whole thing. Up to that point everything was fine...even with sqrt calls.

So the bug seems to be related to the combination of pow function and the vfprintf implementation, as opposed to either one alone.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Post a buildable example.
Or even an example that 'won't' compile that particular line.

GCC sometimes tries to be too clever. For example, I would not be surprised if it replaced pow(n, 0.5) with a sqrt(n)

Personally, I don't really care how it does something as long as it works.

This is why your topic is particularly interesting. (i.e. because it fails)

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did post an example. It's in the first link. But here's a slightly modified version

/* torture.c */
#include 

int main(void)
{
  volatile double a;
  double c;
  a = 32.0;
  c = pow(a, 1.0/3.0);
  if (c + 0.1 > 3.174802
      && c - 0.1 < 3.174802)
    return 0;
  else
    return -1;
}

This works:

Quote:
avr-gcc -O2 -mmcu=atmega128 -lm torture.c

This fails:
Quote:
avr-gcc -O2 -mmcu=atmega128 -Wl,-u,vfprintf -lprintf_flt -lm torture.c

Adding a printf is moot.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I usually compile first, then link

avr-gcc -O2 -mmcu=atmega128 -c torture.c 
avr-gcc -mmcu=atmega128 torture.o -Wl,-u,vfprintf -lprintf_flt -lm

Or do it your way, but put -lm last.

==================================================================
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That worked! That's really weird. Since I use Jam and a Jamfile, the operations do compile and then link. But it fails there.

Perhaps it's a command-line combination of things, or the order in which things are placed? (the following fails)

Quote:
/mnt/proj/projects/atmel/tools/avr4.7.2/bin/avr-gcc -c -o obj/torture.o -mmcu=atxmega128a1 -Wl,-mstrict-X -std=gnu99 -gstabs -Wa,-acdghlmns=xm128.lst -Os -mcall-prologues -fno-split-wide-types -fno-caller-saves -fno-tree-loop-optimize -I. torture.c

Link obj/xm128.elf

/mnt/proj/projects/atmel/tools/avr4.7.2/bin/avr-gcc -mmcu=atxmega128a1 -mstrict-X -Wl,-Map=xm128.map -Wl,--gc-sections -Wl,-u,vfprintf,-lprintf_flt -lm -Wl,-lm -o obj/xm128.elf obj/torture.o

I'll have to try adding my usart and printf to this example and test it out on my xmega...TBD...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I built in AS6 and ran it on an Arduino:

#include 
extern void initstdio(void);

#include 

void main(void)
{
    volatile double a;
    double c;
    initstdio();
    printf("fpserial\r\n");
    for (a = 32.0; a < 1e12; a *= 100) {
        c = pow(a, 0.25);
        printf("pow(% f, 0.25) = % f\r\n", a, c);
    }
    while (1);
}

Output was:

fpserial
pow(32.000000, 0.25) = 2.378414
pow(3200.000000, 0.25) = 7.521204
pow(320000.000000, 0.25) = 23.784136
pow(32000000.000000, 0.25) = 75.212036
pow(3200000000.000000, 0.25) = 237.841380
pow(320000000000.000000, 0.25) = 752.120060

I can build it for a mega128 if you like.
I suppose I could build it in Ubuntu if you were to quote all your tool version numbers.

Sorry, I did not dare compile your code. How can you use return statements from an inherently void main() function ?

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OMG! I just pulled out an old makefile and built some test code.

Now it works!!

I haven't used make for my AVR projects in 3 years. I guess I'll have to go back to using Makefiles again.

Thanks for your help guys... I should have asked this yesterday.

But then I wouldn't have a nice newly compiled compiler :)
Maybe I'll recompile it again with --with-avrlibc as per the link provided by SprinterSB.

It turns out it ALL stems from not having -lm at the very end of the link line. Jam places the objects after the options, and for -lm that won't work.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
It turns out it ALL stems from not having -lm at the very end of the link line. Jam places the objects after the options, and for -lm that won't work.

Surely this is Jam's fault.
Any traditional cc command line expects -l switches to be after the objects... list.

Having never heard of or used Jam, does it have any particular advantages over a conventional Make?

I gather that there is no point in me testing AS6 + pow + printf + mega128.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Having never heard of or used Jam, does it have any particular advantages over a conventional Make?

The image (Table 1) here appears to be the argument for it:

http://www.perforce.com/document...

(i.e. a simpler Make "language").

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah-ha. It looks as if you can create as many complex "Rules" as you like.

In which case, I guess that kmceng simply has to get the "LD" rule syntactically correct. And you could add specific switches in the necessary order on the command line.

You certainly have complete control with a conventional Makefile.

Personally, I have lived with Make for a long time. Once you have a skeleton layout, it is pretty simple to customise. (and I am too old to learn new tricks)

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I went back to Jam and took a look in the Jambase file which controls things. It turns out if I stick the -lm into the LINKLIBS definition instead of the LINKFLAGS definition, it will go properly at the end of the object files as in

Quote:
$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)

Now my 'old' compiler works too. But as the adjacent thread about R_AVR_13_PCREL errors suggests, this may not be the last I ever see of it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So you can configure the Jam as well as a regular Makefile.

Just that the syntax might be simpler !

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, but similar too. Perforce Jam is an old program and no longer supported, but there is boost-jam and ftjam which are more current.

The thing I like best, is when you change an include file, Jam knows it and auto compiles the needed sources. Unless you jump through hoops with makefiles, that doesn't happen. I didn't always remember to 'make -B' to rebuild everything, and it annoyed me enough to learn Jam.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you want to explore a "level above make" I'd have though Cmake would be the choice. We use it for all our large projects and after a while I think I've just about got the hand of the "language".

http://www.cmake.org/

One of it's advantages is that for the same source I can have it generate .sln and .vcproj files for use with MS Visual Studio or for Linux a GNU Makefile. In fact from the one CMakeLists.txt for a project it can generate project/makefiles for all the following:

http://cmake.org/cmake/help/v2.8...