Hi all,
Could somebody explain, please, why if I pass a structure by value to a function, it’s sometimes passed by reference without byval attribute?
Consider an example (Compiler Explorer). Say we have C code:
struct S {
int a[100];
int b;
};
void func1(struct S s) {
s.b = 111;
}
void func2(struct S *s) {
s->b = 222;
}
If I compile with clang 15 for arm64:
-O0 -Xclang -no-opaque-pointers -emit-llvm -S
I get something like:
define dso_local void @func1(%struct.S* noundef %0) #0 !dbg !10 {
%2 = getelementptr inbounds %struct.S, %struct.S* %0, i32 0, i32 1, !dbg !25
store i32 111, i32* %2, align 4, !dbg !26
ret void, !dbg !27
}
define dso_local void @func2(%struct.S* noundef %0) #0 !dbg !28 {
%2 = alloca %struct.S*, align 8
store %struct.S* %0, %struct.S** %2, align 8
%3 = load %struct.S*, %struct.S** %2, align 8, !dbg !34
%4 = getelementptr inbounds %struct.S, %struct.S* %3, i32 0, i32 1, !dbg !35
store i32 222, i32* %4, align 4, !dbg !36
ret void, !dbg !37
}
From here, I cannot understand, 1) why func1 IR works as passing by value, while func2 provides passing by reference,
2) why store i32 111, i32* %2, align 4
from func1 does not modify the structure field,
3) and why do we even need extra store and load in func2:
%2 = alloca %struct.S*, align 8
store %struct.S* %0, %struct.S** %2, align 8
%3 = load %struct.S*, %struct.S** %2, align 8, !dbg !34