We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Good day!
I am use Keil uVision v5.28, CLang v6.12.
I noticed an interesting feature on the '-Os balanced' and '-O1' optimization levels.
My code
static void Write(SPI_TypeDef *spi, u16 addr, u32 data, u8 size) { if(size > 0 && size < 5) { const u8 sht[] = {0, 8, 16, 24}; u8 buf[] = { 0x40, addr >> 11, addr >> 3, addr << 5, data >> sht[size - 1 & 0x3], data >> sht[size - 2 & 0x3], data >> sht[size - 3 & 0x3], data }, *p = buf, i = 4 + size; while(i--) { spi->DR = *p++; while(~spi->SR & SPI_SR_RXNE); (void)spi->DR; } } }
I am sending a flexible array to SPI.This array stores a header with an address, transaction type and data (1, 2 or 4 bytes in Big-Endian format).
I get the following listing
0x08001394 F1A30C01 SUB r12,r3,#0x01 0x08001398 FA5FFC8C UXTB r12,r12 0x0800139C F1BC0F03 CMP r12,#0x03 0x080013A0 D844 BHI 0x0800142C 0x080013A2 B580 PUSH {r7,lr} 0x080013A4 B082 SUB sp,sp,#0x08 0x080013A6 F04F0C40 MOV r12,#0x40 76: addr << 5, 77: data >> sht[size - 1 & 0x3], 78: data >> sht[size - 2 & 0x3], 0x080013AA EA4F1E41 LSL lr,r1,#5 72: { 73: 0x40, 74: addr >> 11, 0x080013AE F88DC000 STRB r12,[sp,#0x00] 0x080013B2 F88DE003 STRB lr,[sp,#0x03] 75: addr >> 3, 76: addr << 5, 77: data >> sht[size - 1 & 0x3], 78: data >> sht[size - 2 & 0x3], 0x080013B6 EA4F0ED1 LSR lr,r1,#3 74: addr >> 11, 75: addr >> 3, 76: addr << 5, 77: data >> sht[size - 1 & 0x3], 78: data >> sht[size - 2 & 0x3], 0x080013BA 0AC9 LSRS r1,r1,#11 72: { 0x080013BC F88DE002 STRB lr,[sp,#0x02] 0x080013C0 F88D1001 STRB r1,[sp,#0x01] 79: data >> sht[size - 3 & 0x3], 80: data 81: }, *p = buf, i = 4 + size; 82: while(i--) 83: { 0x080013C4 1C59 ADDS r1,r3,#1 77: data >> sht[size - 1 & 0x3], 78: data >> sht[size - 2 & 0x3], 0x080013C6 F6427E00 MOVW lr,#0x2F00 72: { 73: 0x40, 74: addr >> 11, 75: addr >> 3, 76: addr << 5, 77: data >> sht[size - 1 & 0x3], 78: data >> sht[size - 2 & 0x3], 0x080013CA F88D2007 STRB r2,[sp,#0x07] 79: data >> sht[size - 3 & 0x3], 80: data 81: }, *p = buf, i = 4 + size; 82: while(i--) 83: { 0x080013CE F0010103 AND r1,r1,#0x03 77: data >> sht[size - 1 & 0x3], 0x080013D2 F6C00E00 MOVT lr,#0x800 79: data >> sht[size - 3 & 0x3], 0x080013D6 F81E1001 LDRB r1,[lr,r1] 79: data >> sht[size - 3 & 0x3], 0x080013DA FA22F101 LSR r1,r2,r1 72: { 73: 0x40, 74: addr >> 11, 75: addr >> 3, 76: addr << 5, 77: data >> sht[size - 1 & 0x3], 0x080013DE F88D1006 STRB r1,[sp,#0x06] 78: data >> sht[size - 2 & 0x3], 79: data >> sht[size - 3 & 0x3], 80: data 81: }, *p = buf, i = 4 + size; 82: while(i--) 83: { 0x080013E2 1C99 ADDS r1,r3,#2 0x080013E4 F0010103 AND r1,r1,#0x03 78: data >> sht[size - 2 & 0x3], 0x080013E8 F81E1001 LDRB r1,[lr,r1] 78: data >> sht[size - 2 & 0x3], 0x080013EC FA22F101 LSR r1,r2,r1 72: { 73: 0x40, 74: addr >> 11, 75: addr >> 3, 76: addr << 5, 77: data >> sht[size - 1 & 0x3], 78: data >> sht[size - 2 & 0x3], 79: data >> sht[size - 3 & 0x3], 80: data 81: }, *p = buf, i = 4 + size; 82: while(i--) 83: { 0x080013F0 F88D1005 STRB r1,[sp,#0x05] 77: data >> sht[size - 1 & 0x3], 0x080013F4 1CD9 ADDS r1,r3,#3 0x080013F6 F0010303 AND r3,r1,#0x03 77: data >> sht[size - 1 & 0x3], 0x080013FA F81E3003 LDRB r3,[lr,r3] 77: data >> sht[size - 1 & 0x3], 0x080013FE 40DA LSRS r2,r2,r3 72: { 0x08001400 F88D2004 STRB r2,[sp,#0x04] 0x08001404 466A MOV r2,sp 0x08001406 B002 ADD sp,sp,#0x08 0x08001408 E8BD4080 POP {r7,lr} 84: spi->DR = *p++; 0x0800140C FA5FF38C UXTB r3,r12 84: spi->DR = *p++; 0x08001410 8183 STRH r3,[r0,#0x0C] 0x08001412 BF00 NOP 85: while(~spi->SR & SPI_SR_RXNE); 0x08001414 8903 LDRH r3,[r0,#0x08] 85: while(~spi->SR & SPI_SR_RXNE); 0x08001416 07DB LSLS r3,r3,#31 0x08001418 D0FC BEQ 0x08001414 86: (void)spi->DR; 87: } 88: } 0x0800141A 8983 LDRH r3,[r0,#0x0C] 82: while(i--) 83: { 84: spi->DR = *p++; 85: while(~spi->SR & SPI_SR_RXNE); 86: (void)spi->DR; 87: } 88: } 0x0800141C 060B LSLS r3,r1,#24 89: } 90: 91: void spi_InitSw1(void) 0x0800141E BF08 IT EQ 0x08001420 4770 BX lr 0x08001422 3201 ADDS r2,r2,#0x01 82: while(i--) 83: { 0x08001424 3901 SUBS r1,r1,#0x01 84: spi->DR = *p++; 85: while(~spi->SR & SPI_SR_RXNE); 86: (void)spi->DR; 87: } 88: } 0x08001426 F892C000 LDRB r12,[r2,#0x00] 0x0800142A E7EF B 0x0800140C
As you can see, 8 bytes are reserved for the array on the stack, and it is initialized. But before the loop, this array is freed from the stack! Any interruption will spoil the data in this array.
Why is this happening?
This bug has been fixed in ARM CLang v6.13.