Closed ghost closed 6 years ago
Let's look at the generated assembly.
Without the alloca
llc -march=avr -mcpu=atmega328p ~/avr/mmavr.ll -o mmavr.no_alloca.s
.text
.macosx_version_min 10, 11
.file "/Users/dylanmckay/avr/mmavr.ll"
.globl main
.p2align 1
.type main,@function
main: ; @main
; BB#0: ; %entry
push r16
push r17
push r28
push r29
in r28, 61
in r29, 62
sbiw r28, 13
in r0, 63
cli
out 62, r29
out 63, r0
out 61, r28
call init
ldi r17, 1
ldi r24, 13
ldi r22, 1
call pinMode
ldi r16, 0
std Y+13, r16
ldi r24, 0
ldi r25, 0
std Y+11, r24
std Y+12, r25
std Y+9, r24
std Y+10, r25
std Y+7, r24
std Y+8, r25
ldi r24, 200
ldi r25, 0
std Y+5, r24
std Y+6, r25
call millis
std Y+3, r24
std Y+4, r25
std Y+1, r22
std Y+2, r23
LBB0_1: ; %forever_loop
ldi r24, 0
rjmp LBB0_4
LBB0_2: ; %else
ldi r24, 13
ldi r22, 0
call digitalWrite
std Y+13, r16
LBB0_3: ; %forever_loop
call millis
std Y+3, r24
std Y+4, r25
std Y+1, r22
std Y+2, r23
ldd r18, Y+9
ldd r19, Y+10
ldd r20, Y+11
ldd r21, Y+12
sub r22, r18
sbc r23, r19
sbc r24, r20
sbc r25, r21
ldd r18, Y+5
ldd r19, Y+6
ldd r20, Y+7
ldd r21, Y+8
cp r22, r18
cpc r23, r19
cpc r24, r20
cpc r25, r21
ldi r24, 1
brge LBB0_1
LBB0_4: ; %forever_loop
andi r24, 1
cpi r24, 0
brne LBB0_3
; BB#5: ; %then
ldd r24, Y+1
ldd r25, Y+2
ldd r18, Y+3
ldd r19, Y+4
std Y+11, r18
std Y+12, r19
std Y+9, r24
std Y+10, r25
ldd r24, Y+13
cpi r24, 0
brne LBB0_2
; BB#6: ; %then3
ldi r24, 13
ldi r22, 1
call digitalWrite
std Y+13, r17
rjmp LBB0_3
.Lfunc_end0:
.size main, .Lfunc_end0-main
With the alloca
.text
.macosx_version_min 10, 11
.file "/Users/dylanmckay/avr/mmavr.ll"
.globl main
.p2align 1
.type main,@function
main: ; @main
; BB#0: ; %entry
push r16
push r17
push r28
push r29
in r28, 61
in r29, 62
sbiw r28, 13
in r0, 63
cli
out 62, r29
out 63, r0
out 61, r28
call init
ldi r17, 1
ldi r24, 13
ldi r22, 1
call pinMode
ldi r16, 0
std Y+13, r16
ldi r24, 0
ldi r25, 0
std Y+11, r24
std Y+12, r25
std Y+9, r24
std Y+10, r25
std Y+7, r24
std Y+8, r25
ldi r24, 200
ldi r25, 0
std Y+5, r24
std Y+6, r25
call millis
std Y+3, r24
std Y+4, r25
std Y+1, r22
std Y+2, r23
LBB0_1: ; %forever_loop
ldi r24, 0
rjmp LBB0_4
LBB0_2: ; %else
ldi r24, 13
ldi r22, 0
call digitalWrite
std Y+13, r16
LBB0_3: ; %forever_loop
in r24, 61
in r25, 62
sbiw r24, 2
in r0, 63
cli
out 62, r25
out 63, r0
out 61, r24
call millis
std Y+3, r24
std Y+4, r25
std Y+1, r22
std Y+2, r23
ldd r18, Y+9
ldd r19, Y+10
ldd r20, Y+11
ldd r21, Y+12
sub r22, r18
sbc r23, r19
sbc r24, r20
sbc r25, r21
ldd r18, Y+5
ldd r19, Y+6
ldd r20, Y+7
ldd r21, Y+8
cp r22, r18
cpc r23, r19
cpc r24, r20
cpc r25, r21
ldi r24, 1
brge LBB0_1
LBB0_4: ; %forever_loop
andi r24, 1
cpi r24, 0
brne LBB0_3
; BB#5: ; %then
ldd r24, Y+1
ldd r25, Y+2
ldd r18, Y+3
ldd r19, Y+4
std Y+11, r18
std Y+12, r19
std Y+9, r24
std Y+10, r25
ldd r24, Y+13
cpi r24, 0
brne LBB0_2
; BB#6: ; %then3
ldi r24, 13
ldi r22, 1
call digitalWrite
std Y+13, r17
rjmp LBB0_3
.Lfunc_end0:
.size main, .Lfunc_end0-main
The difference between the two files
diff mmavr.no_alloca.s mmavr.with_alloca.s > mmavr.diff
The alloca
adds the following lines. I have annotated them.
; Load the lower and upper bytes of the stack pointer
in r24, 61
in r25, 62
; Reserve two bytes on the stack
sbiw r24, 2
; load something into memory, don't change it
in r0, 63
cli
; store the stack pointer high bytes
out 62, r25
; put whatever was at IO offset 63 back, even though we didn't modify it
out 63, r0
; store the stack pointer low byte
out 61, r24
What makes you think your chip hangs? What symptoms can you see?
it's pretty weird that this operation disables interrupts. I can understand why you'd want to change the stack pointer atomically, but it's pretty important that you restore the interrupt flag afterwards.
What makes you think your chip hangs? What symptoms can you see?
The LED doesn't blink when I upload that code via avrdude, but when I remove that variable declaration, everything works, the LED blinks. Yes, I don't need that variable, but it's not normal that chip hangs if I declare unnecessary variable in a endless loop. I don't know where is the problem, the .ll output looks fine. As you can see, I'm using arduino-core functions. I suppose that millis()
function using interrupts, but millis()
is "original" arduino function from libcore.a
.
Could you take the assembly file and remove the cli
instruction, compile and try that.
Doesn't work.
So it still has the problem, even without the cli
?
Unfortunately, yes.
I have fixed a bunch of bugs (one of which I'm certain would've broken your code - avr-rust/rust#45).
@mmavr: Does your test case work with the current LLVM master
? Note that this repo hasn't been update for 6+ months and so you'll need to checkout llvm-mirror/llvm and compile with cmake -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR
.
I believe this to be now fixed, and the issue has also become stale.
The current compiler it way more stable than it was at this point. If this is still an issue, we can reopen.
This is the "blink without delay" program in my custom compiler.
When I declare variable in the "forever" loop (%x = alloca i16), the program hangs, but when I comment that line, everything works fine. What could be the problem? I'm using the Arduino UNO (ATMega328p, 16MHz) for testing.