AArch64 doesn't have LEA instruction, so use pointers instead of Effective Address (#21072)

This commit is contained in:
Walter Bright 2025-03-23 22:46:53 -07:00 committed by GitHub
parent 2036516c17
commit 63152e453c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 27 additions and 10 deletions

View file

@ -1067,7 +1067,7 @@ void cdind(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
uint decode(uint to, uint from, bool uns) { return to * 4 * 2 + from * 2 + uns; } uint decode(uint to, uint from, bool uns) { return to * 4 * 2 + from * 2 + uns; }
switch (decode(4, sz, uns)) switch (decode(sz == 8 ? 8 : 4, sz, uns))
{ {
/* /*
int = *byte ldrsb w0,[x1] 39C00020 int = *byte ldrsb w0,[x1] 39C00020

View file

@ -140,6 +140,7 @@ enum
SCSCT = 4, // storage class is valid for use in static ctor SCSCT = 4, // storage class is valid for use in static ctor
SCSS = 8, // storage class is on the stack SCSS = 8, // storage class is on the stack
SCRD = 0x10, // we can do reaching definitions on these SCRD = 0x10, // we can do reaching definitions on these
SCDATA = 0x20, // goes in data segment
} }
// Determine if Symbol has a Ssymnum associated with it. // Determine if Symbol has a Ssymnum associated with it.

View file

@ -3286,6 +3286,8 @@ private elem* elind(elem* e, Goal goal)
switch (e1.Eoper) switch (e1.Eoper)
{ {
case OPrelconst: case OPrelconst:
if (sytab[e1.Vsym.Sclass] & SCDATA && e1.Vsym.Sfl != FL.func && cgstate.AArch64)
break;
e.E1.ET = e.ET; e.E1.ET = e.ET;
e = el_selecte1(e); e = el_selecte1(e);
e.Eoper = OPvar; e.Eoper = OPvar;

View file

@ -2762,8 +2762,11 @@ size_t ElfObj_writerel(int targseg, size_t offset, reltype_t reltype,
{ {
// Elf64_Rela stores addend in Rela.r_addend field // Elf64_Rela stores addend in Rela.r_addend field
sz = relsize64(reltype); sz = relsize64(reltype);
if (!elfobj.AArch64) if (!elfobj.AArch64 || reltype == R_AARCH64_ABS64) // TODO AArch64: extend to all fixups?
{
//printf("writeaddrval() targseg: %d offset: %lld sz: %lld\n", targseg, offset, sz);
writeaddrval(targseg, offset, 0, sz); writeaddrval(targseg, offset, 0, sz);
}
ElfObj_addrel(targseg, offset, reltype, symidx, val); ElfObj_addrel(targseg, offset, reltype, symidx, val);
} }
else else

View file

@ -113,17 +113,17 @@ tym_t pointertype = TYnptr; /* default data pointer type */
* SCxxxx types. * SCxxxx types.
*/ */
char[SCMAX] sytab = ubyte[SCMAX] sytab =
[ [
/* unde */ SCEXP|SCKEP|SCSCT, /* undefined */ /* unde */ SCEXP|SCKEP|SCSCT, /* undefined */
/* auto */ SCEXP|SCSS|SCRD , /* automatic (stack) */ /* auto */ SCEXP|SCSS|SCRD , /* automatic (stack) */
/* static */ SCEXP|SCKEP|SCSCT, /* statically allocated */ /* static */ SCEXP|SCKEP|SCSCT|SCDATA, /* statically allocated */
/* thread */ SCEXP|SCKEP , /* thread local */ /* thread */ SCEXP|SCKEP , /* thread local */
/* extern */ SCEXP|SCKEP|SCSCT, /* external */ /* extern */ SCEXP|SCKEP|SCSCT|SCDATA, /* external */
/* register */ SCEXP|SCSS|SCRD , /* registered variable */ /* register */ SCEXP|SCSS|SCRD , /* registered variable */
/* pseudo */ SCEXP , /* pseudo register variable */ /* pseudo */ SCEXP , /* pseudo register variable */
/* global */ SCEXP|SCKEP|SCSCT, /* top level global definition */ /* global */ SCEXP|SCKEP|SCSCT|SCDATA, /* top level global definition */
/* comdat */ SCEXP|SCKEP|SCSCT, /* initialized common block */ /* comdat */ SCEXP|SCKEP|SCSCT|SCDATA, /* initialized common block */
/* parameter */SCEXP|SCSS , /* function parameter */ /* parameter */SCEXP|SCSS , /* function parameter */
/* regpar */ SCEXP|SCSS , /* function register parameter */ /* regpar */ SCEXP|SCSS , /* function register parameter */
/* fastpar */ SCEXP|SCSS , /* function parameter passed in register */ /* fastpar */ SCEXP|SCSS , /* function parameter passed in register */
@ -144,13 +144,13 @@ char[SCMAX] sytab =
/* overload */ SCEXP , /* for overloaded function names */ /* overload */ SCEXP , /* for overloaded function names */
/* friend */ 0 , /* friend of a class */ /* friend */ 0 , /* friend of a class */
/* virtual */ 0 , /* virtual function */ /* virtual */ 0 , /* virtual function */
/* locstat */ SCEXP|SCSCT , /* static, but local to a function */ /* locstat */ SCEXP|SCSCT|SCDATA, /* static, but local to a function */
/* template */ 0 , /* class template */ /* template */ 0 , /* class template */
/* functempl */0 , /* function template */ /* functempl */0 , /* function template */
/* ftexpspec */0 , /* function template explicit specialization */ /* ftexpspec */0 , /* function template explicit specialization */
/* linkage */ 0 , /* function linkage symbol */ /* linkage */ 0 , /* function linkage symbol */
/* public */ SCEXP|SCKEP|SCSCT, /* generate a pubdef for this */ /* public */ SCEXP|SCKEP|SCSCT, /* generate a pubdef for this */
/* comdef */ SCEXP|SCKEP|SCSCT, /* uninitialized common block */ /* comdef */ SCEXP|SCKEP|SCSCT|SCDATA, /* uninitialized common block */
/* bprel */ SCEXP|SCSS , /* variable at fixed offset from frame pointer */ /* bprel */ SCEXP|SCSS , /* variable at fixed offset from frame pointer */
/* namespace */0 , /* namespace */ /* namespace */0 , /* namespace */
/* alias */ 0 , /* alias to another symbol */ /* alias */ 0 , /* alias to another symbol */

View file

@ -769,7 +769,18 @@ elem* toElem(Expression e, ref IRState irs)
e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, offset)); e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, offset));
} }
else if (se.op == EXP.variable) else if (se.op == EXP.variable)
e = el_var(s); {
if (sytab[s.Sclass] & SCDATA && s.Sfl != FL.func && target.isAArch64)
{
/* AArch64 does not have an LEA instruction,
* so access data segment data via a pointer
*/
e = el_ptr(s);
e = el_una(OPind,s.Stype.Tty,e); // e = * & s
}
else
e = el_var(s);
}
else else
{ {
e = nrvo ? el_var(s) : el_ptr(s); e = nrvo ? el_var(s) : el_ptr(s);