incompatible with avr-gcc7.1

Bug #1703250 reported by Henning
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Flashlight Firmware Repository
Confirmed
Undecided
Unassigned

Bug Description

Hello,
it seems like building fails on avr-gcc 7.1, it happens in an Arch VM and in Windows. Log:

[antergos-avr@antergos-avr hello_world]$ make
  CC STAR_smaller.o
avr-gcc -Wall -g -Os -mmcu=attiny13 -o STAR_smaller.o -c STAR_smaller.c
  LD STAR_smaller.elf
avr-gcc -Wall -g -Os -mmcu=attiny13 -o STAR_smaller.elf STAR_smaller.o
STAR_smaller.o: In function `main':
/home/antergos-avr/flashlight-firmware/hello_world/STAR_smaller.c:(.text.startup+0x10): undefined reference to `ADC_on'
STAR_smaller.o: In function `__vector_8':
/home/antergos-avr/flashlight-firmware/hello_world/STAR_smaller.c:213: undefined reference to `read_mode_idx'
/home/antergos-avr/flashlight-firmware/hello_world/STAR_smaller.c:213: undefined reference to `next_mode'
/home/antergos-avr/flashlight-firmware/hello_world/STAR_smaller.c:213: undefined reference to `WDT_on'
/home/antergos-avr/flashlight-firmware/hello_world/STAR_smaller.c:215: undefined reference to `WDT_off'
collect2: error: ld returned 1 exit status
make: *** [Makefile:15: STAR_smaller.elf] Error 1

C:\Coding\toykeeper\hello_world>make
  CC STAR_smaller.o
avr-gcc -Wall -g -Os -mmcu=attiny13 -o STAR_smaller.o -c STAR_smaller.c
  LD STAR_smaller.elf
avr-gcc -Wall -g -Os -mmcu=attiny13 -o STAR_smaller.elf STAR_smaller.o
STAR_smaller.o: In function `main':
C:\Coding\toykeeper\hello_world/STAR_smaller.c:248: undefined reference to `ADC_on'
C:\Coding\toykeeper\hello_world/STAR_smaller.c:295: undefined reference to `read_mode_idx'
C:\Coding\toykeeper\hello_world/STAR_smaller.c:300: undefined reference to `next_mode'
C:\Coding\toykeeper\hello_world/STAR_smaller.c:307: undefined reference to `WDT_on'
C:\Coding\toykeeper\hello_world/STAR_smaller.c:332: undefined reference to `WDT_off'
collect2.exe: error: ld returned 1 exit status
make: *** [Makefile:15: STAR_smaller.elf] Error 1

C:\Coding\toykeeper\hello_world>

log for make -d: https://pastebin.com/F3WVAQLg

Revision history for this message
Selene ToyKeeper (toykeeper) wrote :

So, gcc 7.1 doesn't support the "inline" keyword by default? What happens if you add -std=gnu99 to the compile options?

The latest available in Debian (even in unstable) is gcc-avr 1:4.9.2+Atmel3.5.4-1. I'm not sure what all changed between gcc 4 and gcc 7, but some platforms failed by merely switching from 4 to 5. I expect to see a wide variety of problems for pretty much any project which uses gcc.

For this project, it looks like the inline functions may need to be declared as external, to trick the linker into not trying to resolve them. If -std=gnu99 doesn't work, what happens if you change those to "extern inline" instead of just "inline"?

Changed in flashlight-firmware:
status: New → Incomplete
Revision history for this message
Henning (wuelpi) wrote :

Adding -std=gnu99 to the CFLAGS does nothing, while using extern inline to the functions, that are throwing the errors, works. -std=gnu89 works with just inline, but adds 4 byte. Sizes differ by a surprising amount, just in case you are interested:

extern inline and -std=gnu89 OR extern inline and -fgnu89-inline
   text data bss dec hex filename
      0 940 0 940 3ac STAR_smaller.hex

extern inline (same with -std=gnu99 and without)
   text data bss dec hex filename
      0 952 0 952 3b8 STAR_smaller.hex

-std=gnu89
   text data bss dec hex filename
      0 956 0 956 3bc STAR_smaller.hex

precompiled
   text data bss dec hex filename
      0 972 0 972 3cc precompiled.hex

Revision history for this message
Selene ToyKeeper (toykeeper) wrote :

Interesting. Thanks! I don't have easy access to avr-gcc-7 yet, but this should be very helpful when that's more widely used. I'll also have to do some testing to find the smallest compile options during the next updates.

I'm not sure there will be a single set of options which works best with all recent versions of gcc though... For example, here's what I'm getting with biscotti on gcc-4.9.2:

-std=gnu99 and no externs: 1022 bytes

-std=gnu89 and no externs: 1066 bytes

-std=gnu99 and extern inline: 1058 bytes

-std=gnu89 and extern inline: 1030 bytes

With -std=gnu11, I get the same results as gnu99.

Since only one of these fits under the 1024-byte limit, it might need to use different build options for different versions of gcc, and possibly replace some built-in keywords with version-specific #defines. The changes required to make it compile with gcc-7.1 have a side effect of breaking the gcc-4.9.2 build.

Changed in flashlight-firmware:
status: Incomplete → Confirmed
Revision history for this message
Henning (wuelpi) wrote :

I was interested how everything behaves and got avr-gcc 5.4 to work on OpenSuse Tumbleweed (my main Distro) so here are tests with 5.4 and biscotti:

OpenSuse Tumbleweed GCC 5.4

no extern
-std=gnu11 1020 bytes
-std=gnu99 1020 bytes
-std=gnu89 1082 bytes
-std=gnu11 -fgnu11-inline 1082 bytes
-std=gnu99 -fgnu99-inline 1082 bytes
-std=gnu89 -fgnu89-inline 1082 bytes
extern inline
-std=gnu11 1078 bytes
-std=gnu99 1078 bytes
-std=gnu89 1024 bytes
-std=gnu11 -fgnu89-inline 1024 bytes
-std=gnu99 -fgnu89-inline 1024 bytes
-std=gnu89 -fgnu89-inline 1024 bytes

And as I have the VM up and running, here are the 7.1 results on arch:
no extern
-std=gnu11 fails
-std=gnu99 fails
-std=gnu89 1082 bytes
-std=gnu89 -fgnu11-inline 1082 bytes
-std=gnu89 -fgnu99-inline 1082 bytes
-std=gnu89 -fgnu89-inline 1082 bytes
extern inline
-std=gnu11 1078 bytes
-std=gnu99 1078 bytes
-std=gnu89 1026 bytes
-std=gnu11 -fgnu89-inline 1026 bytes
-std=gnu99 -fgnu89-inline 1026 bytes
-std=gnu89 -fgnu89-inline 1026 bytes

Both times avr-libc 2.0

I'll see how easy it is to update GCC to 6 and 7 on TW (it is a different repo and has problems) and will add results in case it works.

Revision history for this message
Henning (wuelpi) wrote :

I found a way to downgrade on arch, this is the most hassle free at the moment. The results are to no surprise the same for 5.3 on Arch and 5.4 on TW. For GCC 6.3 it was exactly the same as 7.1 but without failing:

no extern
-std=gnu11 1022 bytes
-std=gnu99 1022 bytes
-std=gnu89 1082 bytes
-std=gnu11 -fgnu89-inline 1082 bytes
-std=gnu99 -fgnu89-inline 1082 bytes
-std=gnu89 -fgnu89-inline 1082 bytes
extern inline
-std=gnu11 1078 bytes
-std=gnu99 1078 bytes
-std=gnu89 1026 bytes
-std=gnu11 -fgnu89-inline 1026 bytes
-std=gnu99 -fgnu89-inline 1026 bytes
-std=gnu89 -fgnu89-inline 1026 bytes

-Winline shows lots of functions not being inlined without -fgnu89-inline: https://pastebin.com/sxRDnQS6 due to GCC thinking it would let the code size grow. I would assume this is the biggest cuprit. Maybe I try to experiment with __attribute__((always_inline)), a short try failed though.

Small correction for my last posting, I mixed up the build options, it's -fgnu89-inline every time and the standard changes.

Revision history for this message
Henning (wuelpi) wrote :

I have looked up the changes that C99 brought to the inline keyword and changed the functions that threw an error to static inline and this results in no code size regression.

GCC 7
static inline
-std=gnu11 1022 bytes
-std=gnu99 1022 bytes
-std=gnu89 1026 bytes
-std=gnu11 -fgnu89-inline 1026 bytes
-std=gnu99 -fgnu89-inline 1026 bytes
-std=gnu89 -fgnu89-inline 1026 bytes

GCC 5
static inline
-std=gnu11 1020 bytes
-std=gnu99 1020 bytes
-std=gnu89 1024 bytes
-std=gnu11 -fgnu89-inline 1024 bytes
-std=gnu99 -fgnu89-inline 1024 bytes
-std=gnu89 -fgnu89-inline 1024 bytes

Has static inline regressions on your GCC 4.9?

I believe all the cases that blew up the code size by a larger margin (40+ byte) came from the compiler not inlining the functions. -Winline seems to be a good addition to the build scripts to spot this kind of stuff, in my opinion.

I'll try to figure out why GCC 5 uses one instruction less in versions 4.9, 6 and 7 and if it's a bug in GCC 5 that produces smaller, but incorrect code or if it's a code size regression in 6 and 7.

Revision history for this message
Dmytro Borshchanenko (parmaster) wrote :

Same with GCC 8
"extern inline" hack solves the issue, Anduril had been successfully compiled on MacOs High Sierra with gcc and avr-gcc installed with Brew without specifying the versions etc (all default)

Revision history for this message
Leo (leo-died-again) wrote :

Same with GCC 9.1. Replacing externing the inline fixes this for GCC 9.1 at least for the hello_world example.

Revision history for this message
Dan Nelson (dnelson1901) wrote :

I'm using avr-gcc 9.1 and worked around the issue with the -fgnu89-inline flag. That way no code needs to be changed.

Revision history for this message
Sven Greiner (sammyshp) wrote :

Your fix from https://bazaar.launchpad.net/~toykeeper/flashlight-firmware/trunk/revision/237 has a code size regression.

With gcc 9.2.0 and using https://bazaar.launchpad.net/~toykeeper/flashlight-firmware/fsm/revision/443:

FW3A:
  Your fix: 7854 bytes
  static inline: 7834 bytes

D4V2:
  Your fix: 9234 bytes
  static inline: 9158 bytes

"static inline" means not using your compile option changes and replacing all instances of "inline" with "static inline" as done in this commit: https://github.com/SammysHP/flashlight-firmware/commit/a73df6d00831ad326a3eeb62a17994a9b50ac9f1

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.