This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/AM4379: Function argument type conversion ignored when it passed to another function

Part Number: AM4379

Tool/software: TI C/C++ Compiler

Hello,

I probably have found a bug in TI PRU Code Generation Tools 2.3.3. It is leads in passing invalid values to function on implicit conversions.

Here is an example:

#include <stdint.h>
#include <string.h>

void memcpy16(void *dst, void *src, uint16_t size)
{
	memcpy(dst, src, size);
}

void memcpy32(void *dst, void *src, uint32_t size)
{
	memcpy(dst, src, size);
}

volatile void *src;
volatile void *dst;
volatile uint16_t size;

void test(void)
{
	memcpy16(src, dst, size);
	memcpy32(src, dst, size);
}

void main(void)
{
	test();
}

Here, the memcpy() function call is enclosed in two almost identical functions memcpy16 and memcpy32. Functions differ only in the type of size argument.

I have expect two implicit conversions:
  1. in call of memcpy32 size argument must be converted from uin16_t to uint32_t;
  2. in call of memcpy inside memcpy16 size argument must be converted from uint32_t to size_t.

I have compiled this program and get assembly listing with dispru.

TEXT Section .text (Little Endian), 0xd8 bytes at 0x0000001c 
0x0000001c                   test:
0x0000001c                   main:
0000001c     050ee2e2      SUB R2, R2, 14
00000020     e100c2c3      SBBO &R3.b2, R2, 0, 14
00000024     240104e6      LDI R6, 260
00000028     240100e5      LDI R5, 256
0000002c     240108e4      LDI R4, 264
00000030     f100268e      LBBO &R14.b0, R6, 0, 4
00000034     f100258f      LBBO &R15.b0, R5, 0, 4
00000038     f1000490      LBBO &R16.b0, R4, 0, 2
0000003c     230025c3      JAL R3.w2, memcpy16
00000040     f1000480      LBBO &R0.b0, R4, 0, 2
00000044     f100268e      LBBO &R14.b0, R6, 0, 4
00000048     f100258f      LBBO &R15.b0, R5, 0, 4
0000004c     108080f0      AND R16, R0.w0, R0.w0
00000050     23002fc3      JAL R3.w2, memcpy32
00000054     f100c2c3      LBBO &R3.b2, R2, 0, 14
00000058     010ee2e2      ADD R2, R2, 14
0000005c     20c30000      JMP R3.w2
0x00000060                   memcpy:
00000060     5100f00c      QBEQ return, R16, 0
00000064     10eeeef1      AND R17, R14, R14
0x00000068                   start:
00000068     24003000      LDI R0.b0, 48
0000006c     70f00002      QBGE copy, R0.b0, R16
00000070     10f0f000      AND R0.b0, R16, R16
0x00000074                   copy:
00000074     0400f0f0      SUB R16, R16, R0.b0
00000078     ff00cf12      LBBO &R18.b0, R15, 0, 125
0000007c     ef00d112      SBBO &R18.b0, R17, 0, 125
00000080     5100f004      QBEQ return, R16, 0
00000084     0000efef      ADD R15, R15, R0.b0
00000088     0000f1f1      ADD R17, R17, R0.b0
0000008c     21001a00      JMP start
0x00000090                   return:
00000090     20c30000      JMP R3.w2
0x00000094                   memcpy16:
00000094     0502e2e2      SUB R2, R2, 2
00000098     e10002c3      SBBO &R3.b2, R2, 0, 2
0000009c     10000000      AND R0.b0, R0.b0, R0.b0
000000a0     10000000      AND R0.b0, R0.b0, R0.b0
000000a4     10000000      AND R0.b0, R0.b0, R0.b0
000000a8     10000000      AND R0.b0, R0.b0, R0.b0
000000ac     230018c3      JAL R3.w2, memcpy
000000b0     f10002c3      LBBO &R3.b2, R2, 0, 2
000000b4     0102e2e2      ADD R2, R2, 2
000000b8     20c30000      JMP R3.w2
0x000000bc                   memcpy32:
000000bc     0502e2e2      SUB R2, R2, 2
000000c0     e10002c3      SBBO &R3.b2, R2, 0, 2
000000c4     10000000      AND R0.b0, R0.b0, R0.b0
000000c8     10000000      AND R0.b0, R0.b0, R0.b0
000000cc     10000000      AND R0.b0, R0.b0, R0.b0
000000d0     10000000      AND R0.b0, R0.b0, R0.b0
000000d4     230018c3      JAL R3.w2, memcpy
000000d8     f10002c3      LBBO &R3.b2, R2, 0, 2
000000dc     0102e2e2      ADD R2, R2, 2
000000e0     20c30000      JMP R3.w2
0x000000e4                   abort:
000000e4     23003bc3      JAL R3.w2, C$$EXIT
0x000000e8                   $C$L1:
000000e8     21003a00      JMP $C$L1
0x000000ec                   C$$EXIT:
0x000000ec                   loader_exit:
000000ec     10000000      AND R0.b0, R0.b0, R0.b0
000000f0     20c30000      JMP R3.w2
In assembly first conversion is done by AND instuction on offset 0000004c.

Second conversion is not found:

  1. offset 00000038: size is placed in first two bytes of R16;
  2. offset 0000003c: call memcpy16;
  3. offset 000000ac: memcpy16 does nothing with R16 and just call memcpy;
  4. offset 00000060: memcpy use R16 as 32-bit value.

Is it right place to post such reports?

  • Unfortunately, I am unable to reproduce the issue.  Please show the build options exactly as the compiler sees them.  Please copy-n-paste the text of the build options, and don't use a screen shot.

    Thanks and regards,

    -George  

  • Build commands (pru1_0.c - name of the source file):

    clpru -v3 -O0 --endian=little --hardware_mac=on --c99 pru1_0.c -z -llibc.a --reread_libs --warn_sections --ram_model pru1.cmd -m  pru1_0.map -o pru1_0.elf
    dispru pru1_0.elf > pru1_0.asm
    

    Contents of pru1.cmd:

    -stack 0x100
    
    /* Specify the System Memory Map */
    MEMORY
    {
    	PAGE 0:
    
    	/* 12kB PRU-ICSS1 Instruction RAM */
    	PRU_IMEM		: org = 0x00000000 len = 0x00003000
    
    	PAGE 1:
    
    	/* RAM */
    
    	/* 8kB PRU Data RAM 0_1 */
    	PRU_DMEM_0_1	: org = 0x00000000 len = 0x00002000
    	/* 8kB PRU Data RAM 1_0 */
    	PRU_DMEM_1_0	: org = 0x00002000 len = 0x00002000
    
    	PRU_SRAM		: org = 0x00010000 len = 0x00008000 CREGISTER=28 /* 32kB Shared RAM */
    	DDR			    : org = 0x80000000 len = 0x00000100	CREGISTER=31
    	L3OCMC			: org = 0x40000000 len = 0x00010000	CREGISTER=30
    
    	/* Peripherals */
    
    	PRU_CFG			: org = 0x00026000 len = 0x00000120	CREGISTER=4
    	PRU_ECAP		: org = 0x00030000 len = 0x00000060	CREGISTER=3
    	PRU_IEP			: org = 0x0002E000 len = 0x0000031C	CREGISTER=26
    	PRU_INTC		: org = 0x00020000 len = 0x00001504	CREGISTER=0
    	PRU_UART		: org = 0x00028000 len = 0x00000038	CREGISTER=7
    
    	DCAN0			: org = 0x481CC000 len = 0x000001E8	CREGISTER=14
    	DCAN1			: org = 0x481D0000 len = 0x000001E8	CREGISTER=15
    	DMTIMER2		: org = 0x48040000 len = 0x0000005C	CREGISTER=1
    	PWMSS0			: org = 0x48300000 len = 0x000002C4	CREGISTER=18
    	PWMSS1			: org = 0x48302000 len = 0x000002C4	CREGISTER=19
    	PWMSS2			: org = 0x48304000 len = 0x000002C4	CREGISTER=20
    	GEMAC			: org = 0x4A100000 len = 0x0000128C	CREGISTER=9
    	I2C1			: org = 0x4802A000 len = 0x000000D8	CREGISTER=2
    	I2C2			: org = 0x4819C000 len = 0x000000D8	CREGISTER=17
    	MBX0			: org = 0x480C8000 len = 0x00000140	CREGISTER=22
    	MCASP0_DMA		: org = 0x46000000 len = 0x00000100	CREGISTER=8
    	MCSPI0			: org = 0x48030000 len = 0x000001A4	CREGISTER=6
    	MCSPI1			: org = 0x481A0000 len = 0x000001A4	CREGISTER=16
    	MMCSD0			: org = 0x48060000 len = 0x00000300	CREGISTER=5
    	SPINLOCK		: org = 0x480CA000 len = 0x00000880	CREGISTER=23
    	TPCC			: org = 0x49000000 len = 0x00001098	CREGISTER=29
    	UART1			: org = 0x48022000 len = 0x00000088	CREGISTER=11
    	UART2			: org = 0x48024000 len = 0x00000088	CREGISTER=12
    
    	RSVD10			: org = 0x48318000 len = 0x00000100	CREGISTER=10
    	RSVD13			: org = 0x48310000 len = 0x00000100	CREGISTER=13
    	RSVD21			: org = 0x00032400 len = 0x00000100	CREGISTER=21
    	RSVD27			: org = 0x00032000 len = 0x00000100	CREGISTER=27
    }
    
    /* Specify the sections allocation into memory */
    SECTIONS {
    	/* Forces _c_int00 to the start of PRU IRAM */
    	.text:_c_int00*	>  0x0, PAGE 0
    	.text		>  PRU_IMEM, PAGE 0
    
    	.stack		>  PRU_DMEM_0_1, PAGE 1
    	.bss		>  PRU_DMEM_0_1, PAGE 1
    	.cio		>  PRU_DMEM_0_1, PAGE 1
    	.cinit		>  PRU_DMEM_0_1, PAGE 1
    	.data		>  PRU_DMEM_0_1, PAGE 1
    	.switch		>  PRU_DMEM_0_1, PAGE 1
    	.sysmem		>  PRU_DMEM_0_1, PAGE 1
    	.rodata		>  PRU_DMEM_0_1, PAGE 1
    	.rofardata	>  PRU_DMEM_0_1, PAGE 1
    	.farbss		>  PRU_DMEM_0_1, PAGE 1
    	.fardata	>  PRU_DMEM_0_1, PAGE 1
    }
    

    My real use case is more complicated. I had tried to made minimal example of the problem. Sorry if it is not clear enough.

    Here is a little changed example:

    #include <stdint.h>
    #include <string.h>
    
    void memcpy16(void *dst, void *src, uint16_t size)
    {
        memcpy(dst, src, size);
    }
    
    volatile void *src;
    volatile void *dst;
    volatile uint16_t size;
    
    void main(void)
    {
        strncpy(dst, src, 0x10000);
        memcpy16(dst, src, size);
    }
    

    Compiled with same commands results in this assembly listing:

    TEXT Section .text:_c_int00* (Little Endian), 0x1c bytes at 0x00000000 
    0x00000000                   _c_int00_noinit_noargs:
    00000000     240000c0      LDI R0.w2, 0
    00000004     24010080      LDI R0.w0, 256
    00000008     0504e0e2      SUB R2, R0, 4
    0000000c     2eff818e      XIN 255, &R14.b0, 4
    00000010     230007c3      JAL R3.w2, main
    00000014     240001ee      LDI R14, 1
    00000018     23003bc3      JAL R3.w2, abort
    
    TEXT Section .text (Little Endian), 0xe0 bytes at 0x0000001c 
    0x0000001c                   main:
    0000001c     0502e2e2      SUB R2, R2, 2
    00000020     240100e1      LDI R1, 256
    00000024     e10002c3      SBBO &R3.b2, R2, 0, 2
    00000028     f100218e      LBBO &R14.b0, R1, 0, 4
    0000002c     f1042180      LBBO &R0.b0, R1, 4, 4
    00000030     0501eef0      SUB R16, R14, 1
    00000034     0501e0ef      SUB R15, R0, 1
    00000038     240001ce      LDI R14.w2, 1
    0000003c     2400008e      LDI R14.w0, 0
    0x00000040                   $C$L1:
    00000040     0101f0f0      ADD R16, R16, 1
    00000044     0101e0e0      ADD R0, R0, 1
    00000048     f1001011      LBBO &R17.b0, R16, 0, 1
    0000004c     0101efef      ADD R15, R15, 1
    00000050     e1000f11      SBBO &R17.b0, R15, 0, 1
    00000054     51001103      QBEQ $C$L2, R17.b0, 0
    00000058     0501eeee      SUB R14, R14, 1
    0000005c     6f00eef9      QBNE $C$L1, R14, 0
    0x00000060                   $C$L2:
    00000060     10eeeeef      AND R15, R14, R14
    00000064     0501efee      SUB R14, R15, 1
    00000068     7101ef06      QBGE $C$L4, R15, 1
    0000006c     2eff818f      XIN 255, &R15.b0, 4
    0x00000070                   $C$L3:
    00000070     e100000f      SBBO &R15.b0, R0, 0, 1
    00000074     0101e0e0      ADD R0, R0, 1
    00000078     0501eeee      SUB R14, R14, 1
    0000007c     6f00eefd      QBNE $C$L3, R14, 0
    0x00000080                   $C$L4:
    00000080     240108e0      LDI R0, 264
    00000084     f104218e      LBBO &R14.b0, R1, 4, 4
    00000088     f100218f      LBBO &R15.b0, R1, 0, 4
    0000008c     f1000090      LBBO &R16.b0, R0, 0, 2
    00000090     230035c3      JAL R3.w2, memcpy16
    00000094     f10002c3      LBBO &R3.b2, R2, 0, 2
    00000098     0102e2e2      ADD R2, R2, 2
    0000009c     20c30000      JMP R3.w2
    0x000000a0                   memcpy:
    000000a0     5100f00c      QBEQ return, R16, 0
    000000a4     10eeeef1      AND R17, R14, R14
    0x000000a8                   start:
    000000a8     24003000      LDI R0.b0, 48
    000000ac     70f00002      QBGE copy, R0.b0, R16
    000000b0     10f0f000      AND R0.b0, R16, R16
    0x000000b4                   copy:
    000000b4     0400f0f0      SUB R16, R16, R0.b0
    000000b8     ff00cf12      LBBO &R18.b0, R15, 0, 125
    000000bc     ef00d112      SBBO &R18.b0, R17, 0, 125
    000000c0     5100f004      QBEQ return, R16, 0
    000000c4     0000efef      ADD R15, R15, R0.b0
    000000c8     0000f1f1      ADD R17, R17, R0.b0
    000000cc     21002a00      JMP start
    0x000000d0                   return:
    000000d0     20c30000      JMP R3.w2
    0x000000d4                   memcpy16:
    000000d4     0502e2e2      SUB R2, R2, 2
    000000d8     e10002c3      SBBO &R3.b2, R2, 0, 2
    000000dc     230028c3      JAL R3.w2, memcpy
    000000e0     f10002c3      LBBO &R3.b2, R2, 0, 2
    000000e4     0102e2e2      ADD R2, R2, 2
    000000e8     20c30000      JMP R3.w2
    0x000000ec                   abort:
    000000ec     23003dc3      JAL R3.w2, C$$EXIT
    0x000000f0                   $C$L1:
    000000f0     21003c00      JMP $C$L1
    0x000000f4                   C$$EXIT:
    0x000000f4                   loader_exit:
    000000f4     10000000      AND R0.b0, R0.b0, R0.b0
    000000f8     20c30000      JMP R3.w2

    R16 register usages:

    1. offset 00000030: SUB R16, R14, 1 - load value of src variable minus one
    2. offset 00000040: ADD R16, R16, 1 - part of inlined strncpy, src pointer is incremented to next char
    3. offset 00000048: LBBO &R17.b0, R16, 0, 1 - read one byte from address inside R16 to copy it and check for zero
    4. offset 0000008c: LBBO &R16.b0, R0, 0, 2 - read value of size variable, load only 2 low bytes, 2 high bytes are unknown
    5. offset 000000a0: QBEQ return, R16, 0 - start of memcpy, check that size is not zero, use all 4 bytes in R16, but 2 high bytes are unknown

  • Thank you for the compiler build options.  I can reproduce the problem you show in the first example.  I filed the entry EXT_EP-9623 to have this issue investigated.  You are welcome to search for this issue at this link.

    Thanks and regards,

    -George