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; }
switch (decode(4, sz, uns))
switch (decode(sz == 8 ? 8 : 4, sz, uns))
{
/*
int = *byte ldrsb w0,[x1] 39C00020

View file

@ -140,6 +140,7 @@ enum
SCSCT = 4, // storage class is valid for use in static ctor
SCSS = 8, // storage class is on the stack
SCRD = 0x10, // we can do reaching definitions on these
SCDATA = 0x20, // goes in data segment
}
// 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)
{
case OPrelconst:
if (sytab[e1.Vsym.Sclass] & SCDATA && e1.Vsym.Sfl != FL.func && cgstate.AArch64)
break;
e.E1.ET = e.ET;
e = el_selecte1(e);
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
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);
}
ElfObj_addrel(targseg, offset, reltype, symidx, val);
}
else

View file

@ -113,17 +113,17 @@ tym_t pointertype = TYnptr; /* default data pointer type */
* SCxxxx types.
*/
char[SCMAX] sytab =
ubyte[SCMAX] sytab =
[
/* unde */ SCEXP|SCKEP|SCSCT, /* undefined */
/* auto */ SCEXP|SCSS|SCRD , /* automatic (stack) */
/* static */ SCEXP|SCKEP|SCSCT, /* statically allocated */
/* static */ SCEXP|SCKEP|SCSCT|SCDATA, /* statically allocated */
/* thread */ SCEXP|SCKEP , /* thread local */
/* extern */ SCEXP|SCKEP|SCSCT, /* external */
/* extern */ SCEXP|SCKEP|SCSCT|SCDATA, /* external */
/* register */ SCEXP|SCSS|SCRD , /* registered variable */
/* pseudo */ SCEXP , /* pseudo register variable */
/* global */ SCEXP|SCKEP|SCSCT, /* top level global definition */
/* comdat */ SCEXP|SCKEP|SCSCT, /* initialized common block */
/* global */ SCEXP|SCKEP|SCSCT|SCDATA, /* top level global definition */
/* comdat */ SCEXP|SCKEP|SCSCT|SCDATA, /* initialized common block */
/* parameter */SCEXP|SCSS , /* function parameter */
/* regpar */ SCEXP|SCSS , /* function register parameter */
/* fastpar */ SCEXP|SCSS , /* function parameter passed in register */
@ -144,13 +144,13 @@ char[SCMAX] sytab =
/* overload */ SCEXP , /* for overloaded function names */
/* friend */ 0 , /* friend of a class */
/* 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 */
/* functempl */0 , /* function template */
/* ftexpspec */0 , /* function template explicit specialization */
/* linkage */ 0 , /* function linkage symbol */
/* 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 */
/* namespace */0 , /* namespace */
/* 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));
}
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
{
e = nrvo ? el_var(s) : el_ptr(s);