With arm64, a literal for a nearby address can be loaded into a register with the adr instruction. According to the ARM-V8 Architecture Reference Manual the adr instruction:
ADR ,
can reference labels within +/-1MB. There is a page version with bit-31 set, adrp, for constructing larger offsets.
What I don't understand is why neither gcc 8.2 nor clang 7.0 for ARM64 use adr rather than an adrp and add pair for nearby variables. Optimization levels don't change this.
int write(int fd, const void *buf, int count);
void xyz(void)
{
write(2, "abc", 4);
}
xyz(): // @xyz()
adrp x1, .L.str
add x1, x1, :lo12:.L.str
orr w0, wzr, #0x2
orr w2, wzr, #0x4
b write(int, void const*, int)
.L.str:
.asciz "abc"
Can they not reason that this string literal is within +/-1MB? Is there a compiler attribute/switch to tell them this?