Hi. I’m working on a compiler for a simple language. The language has an array type, which is currently implemented using LLVM arrays. The language also has functions, and I want them to be able to receive arguments of array type. However, I’m not sure if I can (or should, or even if it makes sense to do so) use ArrayType and not a ptr, as a type of the argument in which I pass an array.
Currently, the IR for function definition looks like this:
define void @if_print-array([3 x ptr] %"if/array") {
enter:
...
Later, when I try to call this function, LLVM complains about type mismatch:
Call parameter type does not match function signature!
%17 = getelementptr [3 x ptr], ptr %"if/my-argv", i32 0
[3 x ptr] call void @if_print-array(ptr %17)
I can’t figure out if I can (should) pass an array to it as an array. alloca, which is used to allocate space for the array, returns pointer, getelementptr also returns pointer, and I failed to find any info on how to make an array from ptr.
I can’t figure out if I can (should) pass an array to it as an array. alloca, which is used to allocate space for the array, returns pointer, getelementptr also returns pointer, and I failed to find any info on how to make an array from ptr.
alloca returns the address of the variable you allocated. If you want to get the current value of the variable, you have to use a load instruction to read the value from memory. The getelementptr instruction is essentially an LEA instruction: it merely offsets the input pointer to point to some subobject.
In general, I would recommend avoiding using LLVM array types for SSA variables and instead limit their use to the types of alloca or global variables (and their initializers).
I see. So it is better to pass arrays around as pointers. I suspected as much, and now I feel reassured. I have a difficulty finding best practices about such things in LLVM (or is it not limited to LLVM?).
I had a similar question recently. What helped me the most is going into GodBolt.com and making a small c program which outputs LLVM IR to see how they do it. That answers most questions you will have.
Thank you! Probably you meant Godbolt.org
Also I tried this, but with local instance of clang, which can emit LLVM IR when supplied -S and -emit-llvm flags. I indeed noticed that arrays are passed as pointers. But I wasn’t sure that it is the (only) right way. Probably C has its reasons, which I might not take into consideration, since my language is but a toy one.
The C language explicitly says that arrays “decay” to pointers, so that’s why C always passes an array as a pointer.
Another reason to pass arrays as pointers (or by reference, which is the same thing at machine-code level but different from the language’s semantic viewpoint) is that arrays can be arbitrarily large, which can make it impractical to pass the array by value (i.e., by copying it). A long time ago I worked on a Pascal compiler and we relied on the frontend to enforce read-only semantics in the callee, so that we did not have to copy arrays passed “by value.”