• I’m researching how different ABIs work in relation to implementing tail calls in the Rust compiler. • One thing that I’m currently interested in is if there are ABIs which prohibit the callee from modifying the arguments passed to it by-ref/by-stack. • I tried reading through various ABI specifications, but found them incredibly confusing and hard to find the information I’m interested in… I did some experimentation using the following code: typedef struct { uint64_t a; uint64_t b; uint64_t c; uint64_t d; } Big; void f(Big x); void g(Big x) { f(x); f(x); } void h(Big x) { x.a = 1; f(x); } And for all ABIs I tried: g has to make a copy of x since the first call to f might modify the argument passed to it h doesn’t have to make a copy of x since it’s allowed to modify the argument it receives But is this true for all ABIs (supported by llvm)? • arsenm 2 “by-ref” is the a particularly confusing word choice here. • There are 2 related IR attributes, byval and byref. • byval has an implicit copy performed in the caller, and the pointer visible to the callee is theoretically writable (I’m not aware of anywhere taking advantage of that).
Article Summaries:
- A Rust developer is investigating how different Application Binary Interfaces (ABIs) handle argument passing, specifically whether any ABI forbids a callee from modifying arguments passed by reference. The inquiry centers on tail‑call implementation in the Rust compiler and involves experimenting with a
Bigstruct and functionsf,g, andh. The developer notes that under most ABIs,gmust copy the argument to protect against potential modification byf, whilehcan modify its argument directly. The question also touches on LLVM’sbyvalandbyrefattributes, which control implicit copying and mutability of passed values.
Sources: