avr-llvm / llvm

[MERGED UPSTREAM] AVR backend for the LLVM compiler library
220 stars 21 forks source link

out instruction problem in function call #93

Closed chun92 closed 9 years ago

chun92 commented 9 years ago

I compiled following source code to test the I/O test and I/O doesn't works in function call. Following is the compilation command.

clang --target=avr -I../../include   -mmcu=atmega328p -DF_CPU=16000000UL -Os -w -Wl,--gc-sections -ffunction-sections -fdata-sections flash.cpp -S -o flash.s
#include <avr/io.h>
#include <util/delay.h>

int foo() {
  PORTB = 0XFF;
  return 0;
}

int main (void) {
  DDRB = 0XFF;
  while(1) foo();
}

In original assembly code, function foo is inlined to main function and I check that output works correctly on Arduino Uno board. but when I substitute out 5, r24 to call _Z3foov below the LBB1_1 label, output doesn't works. I'm not sure that I make some stupid mistakes or there are any bugs in clang, but I'm embarrassed to see the I/O fails with regular function body and call instruction which clang generated. (I doubt there is calling convention problem) I found this problem in linking the object files while I build the Arduino libraries.


  .text
  .file "flash.cpp"
  .section  .text,"ax",@progbits,unique,0
  .globl  _Z3foov
  .align  2
  .type _Z3foov,@function
_Z3foov:                                ; @_Z3foov
; BB#0:                                 ; %entry
  ldi r24, -1
  out 5, r24 
  ldi r24, 0
  ldi r25, 0
  ret 
.Lfunc_end0:
  .size _Z3foov, .Lfunc_end0-_Z3foov

  .section  .text,"ax",@progbits,unique,1
  .globl  main
  .align  2
  .type main,@function
main:                                   ; @main
; BB#0:                                 ; %entry
  ldi r24, -1
  out 4, r24 
LBB1_1:                                 ; %while.body
                                        ; =>This Inner Loop Header: Depth=1
  out 5, r24
  rjmp  LBB1_1
.Lfunc_end1:
  .size main, .Lfunc_end1-main
dylanmckay commented 9 years ago

This is an error in AVR-LLVM. I have opened up a new issue for this problem (#94).

Note that if you want to get the code to compile quickly, an easy fix would be to use rcall _Z3foov instead of call _Z3foov. The rcall instruction does not have this problem.

dylanmckay commented 9 years ago

By the way, did you say that you compiled the original code and it ran correctly on Arduino? :P

chun92 commented 9 years ago

The problem occurs when I tried to write the function in the other source. For example, I made the foo() function in foo.h and tried to call foo() in main.cpp, foo() function is called with call _Z3foov instruction. I wonder that the problem is originated from linking problem or instruction problem. :D

dylanmckay commented 9 years ago

LLVM by default lowers calls to a CALL k instruction, which causes an assertion error (see issue #94). We should probably try to use RJMP k instead, as it is more efficient.

With optimisations, the function is inlined, and so a call isn't generated, so the error doesn't call.