Home > Blockchain >  Local initialized array in riscv
Local initialized array in riscv

Time:11-12

I have a c program that comes below:

int A[size][size] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int B[size][size] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int C[size][size];

int multiplication()
{
    //using array A, B and C here

    return 0;
}

I also wrote a startup file by myself and compile them using risc-v compiler by the following command:

riscv64-unknown-elf-gcc -ffreestanding -march=rv32im -mabi=ilp32 -nostartfiles  -nodefaultlibs -mno-relax crt0.s Myprogram.c -o Myprogram

Then using riscv64-unknown-elf-objdump -t Myprogram I can see that arrays A and B are in .data segment and array C is in .bss segment that makes sense.

But when I change my code such that I declared arrays A and B as local arrays to the function:

int C[size][size];

int multiplication()
{
int A[size][size] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int B[size][size] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
    //using array A, B and C here

    return 0;
}

I got the compilation error: undefined reference to `memcpy'. It seems that it uses memcpy for allocating memory to the arrays while it's not the case when I declared the arrays as global.

Does anybody know why and what's the difference?

CodePudding user response:

Large constants needed by a program are stored in the program's text segment, and copied where needed. When the compiler chooses to initialize a large variable by copying the initializer from the text segment, it generates a call to memcpy. There are other ways to compile this code, sure, but calling memcpy is perfectly sensible and efficient.

This doesn't happen for a global variable because they are initialized from the program's data segment. Since they only need to be initialized when the program starts, the same memory that contains the initializer when the program starts is then used for the variable.

You might think of main as a special function and of its local variables as essentially global variables, but they aren't. main is a function, and it can be called recursively. The compiler could in theory detect that some programs doesn't call main recursively and give it special treatment, but in practice, it doesn't, and it sure can't when it's linking some assembly code which could be finding its way to main.

Normally you don't see this because the standard library provides memcpy. But since you're using -nodefaultlibs, you need to supply an alternative implementation of memcmp, memset, memcpy and memmove.

CodePudding user response:

GCC & clang require freestanding environments to provide memcpy, memmove, memset and memcmp.

You need to implement them yourself it you do not want use the standard ones

You should also remember that there are more functions which can be required - for example, integer divisions and similar.

You can also see if your compiler provides libgcc or you can take the function you require from here (or or your port libgcc repo): https://github.com/gcc-mirror/gcc/tree/master/libgcc

  • Related