Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

start on prolog_genvarargs() #20905

Merged
merged 1 commit into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 114 additions & 14 deletions compiler/src/dmd/backend/arm/cod3.d
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,106 @@
// prolog_setupalloca
// prolog_saveregs
// epilog_restoreregs

/******************************
* Generate special varargs prolog for Posix 64 bit systems.
* Params:
* cg = code generator state
* cdb = sink for generated code
* sv = symbol for __va_argsave
*/
@trusted
void prolog_genvarargs(ref CGstate cg, ref CodeBuilder cdb, Symbol* sv)
{
printf("prolog_genvarargs()\n");

Check warning on line 261 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L261

Added line #L261 was not covered by tests
/* Generate code to move any arguments passed in registers into
* the stack variable __va_argsave,
* so we can reference it via pointers through va_arg().
* struct __va_argsave_t {
* ulong[8] regs; // 8 byte
* ldouble[8] fpregs; // 16 byte
* uint offset_regs;
* uint offset_fpregs;
* void* stack_args;
* void* reg_args;
* }
* The instructions seg fault if data is not aligned on
* 16 bytes, so this gives us a nice check to ensure no mistakes.
STR x0,[sp, #voff+6*16+0*8]
STR x1,[sp, #voff+6*16+1*8]
STR x2,[sp, #voff+6*16+2*8]
STR x3,[sp, #voff+6*16+3*8]
STR x4,[sp, #voff+6*16+4*8]
STR x5,[sp, #voff+6*16+5*8]
STR x6,[sp, #voff+6*16+6*8]
STR x7,[sp, #voff+6*16+7*8]

STR q0,[sp, #voff+0*16]
STR q1,[sp, #voff+0*16]
STR q2,[sp, #voff+0*16]
STR q3,[sp, #voff+1*16]
STR q4,[sp, #voff+2*16]
STR q5,[sp, #voff+3*16]
STR q6,[sp, #voff+4*16]
STR q7,[sp, #voff+5*16]

LEA R11, Para.size+Para.offset[RBP]
MOV 9+16[RAX],R11 // set __va_argsave.stack_args
* RAX and R11 are destroyed.
*/

/* Save registers into the voff area on the stack
*/
targ_size_t voff = cg.Auto.size + cg.BPoff + sv.Soffset; // EBP offset of start of sv
const uint vsize = 8 * 8 + 8 * 16;

Check warning on line 301 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L300-L301

Added lines #L300 - L301 were not covered by tests

if (!cg.hasframe || cg.enforcealign)
voff += cg.EBPtoESP;

Check warning on line 304 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L303-L304

Added lines #L303 - L304 were not covered by tests

regm_t namedargs = prolog_namedArgs();

Check warning on line 306 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L306

Added line #L306 was not covered by tests
//printf("voff: %lld\n", voff);
foreach (reg_t x; 0 .. 8)

Check warning on line 308 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L308

Added line #L308 was not covered by tests
{
if (!(mask(x) & namedargs)) // unnamed arguments would be the ... ones

Check warning on line 310 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L310

Added line #L310 was not covered by tests
{
//printf("offset: x%x %lld\n", cast(uint)voff + x * 8, voff + x * 8);
uint offset = cast(uint)voff + vsize - 8 - x * 8;
if (!cg.hasframe || cg.enforcealign)
cdb.gen1(INSTR.str_imm_gen(1,x,31,offset)); // STR x,[sp,#offset]

Check warning on line 315 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L313-L315

Added lines #L313 - L315 were not covered by tests
else
cdb.gen1(INSTR.str_imm_gen(1,x,29,offset)); // STR x,[bp,#offset]

Check warning on line 317 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L317

Added line #L317 was not covered by tests
}
}

foreach (reg_t q; 32 + 0 .. 32 + 8)

Check warning on line 321 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L321

Added line #L321 was not covered by tests
{
if (!(mask(q) & namedargs)) // unnamed arguments would be the ... ones

Check warning on line 323 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L323

Added line #L323 was not covered by tests
{
uint offset = cast(uint)voff + vsize - 8 * 8 - 16 - (q & 31) * 16;
if (!cg.hasframe || cg.enforcealign)
cdb.gen1(INSTR.str_imm_fpsimd(0,2,offset,31,q)); // STR q,[sp,#offset]

Check warning on line 327 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L325-L327

Added lines #L325 - L327 were not covered by tests
else
cdb.gen1(INSTR.str_imm_fpsimd(0,2,offset,29,q));

Check warning on line 329 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L329

Added line #L329 was not covered by tests
}
}

static if (0) // TODO
{
// LEA R11, Para.size+Para.offset[RBP]
uint ea2 = modregxrm(2,R11,BPRM);
if (!cg.hasframe)
ea2 = (modregrm(0,4,SP) << 8) | modregrm(2,DX,4);
cg.Para.offset = (cg.Para.offset + (REGSIZE - 1)) & ~(REGSIZE - 1);
cdb.genc1(LEA,(REX_W << 16) | ea2,FL.const_,cg.Para.size + cg.Para.offset);

// MOV 9+16[RAX],R11
cdb.genc1(0x89,(REX_W << 16) | modregxrm(2,R11,AX),FL.const_,9 + 16); // into stack_args_save

pinholeopt(cdb.peek(), null);
useregs(mAX|mR11);
}
}

// prolog_genvarargs
// prolog_genva_start
// prolog_gen_win64_varargs
Expand Down Expand Up @@ -710,28 +810,28 @@
ubyte imm8;
if (encodeHFD(value, imm8))
{
uint ftype = INSTR.szToFtype(sz);
cdb.gen1(INSTR.fmov_float_imm(ftype,imm8,vreg)); // FMOV <Vd>,#<imm8>
uint ftype = INSTR.szToFtype(sz);
cdb.gen1(INSTR.fmov_float_imm(ftype,imm8,vreg)); // FMOV <Vd>,#<imm8>

Check warning on line 814 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L813-L814

Added lines #L813 - L814 were not covered by tests
}
else if (sz == 4)
{
float f = value;
uint i = *cast(uint*)&f;
regm_t retregs = ALLREGS; // TODO cg.allregs?
reg_t reg = allocreg(cdb, retregs, TYfloat);
movregconst(cdb,reg,i,0); // MOV reg,i
cdb.gen1(INSTR.fmov_float_gen(0,0,0,7,reg,vreg)); // FMOV Sd,Wn
float f = value;
uint i = *cast(uint*)&f;
regm_t retregs = ALLREGS; // TODO cg.allregs?
reg_t reg = allocreg(cdb, retregs, TYfloat);
movregconst(cdb,reg,i,0); // MOV reg,i
cdb.gen1(INSTR.fmov_float_gen(0,0,0,7,reg,vreg)); // FMOV Sd,Wn

Check warning on line 823 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L818-L823

Added lines #L818 - L823 were not covered by tests
}
else if (sz == 8)
{
ulong i = *cast(ulong*)&value;
regm_t retregs = ALLREGS; // TODO cg.allregs?
reg_t reg = allocreg(cdb, retregs, TYdouble);
movregconst(cdb,reg,i,64); // MOV reg,i
cdb.gen1(INSTR.fmov_float_gen(1,1,0,7,reg,vreg)); // FMOV Dd,Xn
ulong i = *cast(ulong*)&value;
regm_t retregs = ALLREGS; // TODO cg.allregs?
reg_t reg = allocreg(cdb, retregs, TYdouble);
movregconst(cdb,reg,i,64); // MOV reg,i
cdb.gen1(INSTR.fmov_float_gen(1,1,0,7,reg,vreg)); // FMOV Dd,Xn

Check warning on line 831 in compiler/src/dmd/backend/arm/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/cod3.d#L827-L831

Added lines #L827 - L831 were not covered by tests
}
else
assert(0);
assert(0);
//cgstate.regimmed_set(vreg,value); // TODO
}

Expand Down
22 changes: 19 additions & 3 deletions compiler/src/dmd/backend/arm/instr.d
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,9 @@
*/
static uint ldst_pos(uint size, uint VR, uint opc, uint imm12, reg_t Rn, reg_t Vt)
{
assert(Vt > 31);
//debug printf("imm12: %x\n", imm12);
assert(imm12 <= 0xFFF);
assert(VR == (Vt > 31));

Check warning on line 954 in compiler/src/dmd/backend/arm/instr.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/instr.d#L953-L954

Added lines #L953 - L954 were not covered by tests
reg_t Rt = Vt & 31;
return (size << 30) |
(7 << 27) |
Expand All @@ -964,12 +966,26 @@
/* https://www.scs.stanford.edu/~zyedidia/arm64/str_imm_fpsimd.html
* STR <Vt>,[<Xn|SP>,#<simm>] Unsigned offset
*/
static uint str_imm_fpsimd(uint size, uint opc, uint imm12, reg_t Rn, reg_t Vt) { return ldst_pos(size,1,opc,imm12,Rn,Vt); }
static uint str_imm_fpsimd(uint size, uint opc, uint offset, reg_t Rn, reg_t Vt)
{
assert(size < 4);
assert(opc < 4);
uint scale = ((opc & 2) << 1) | size;
uint imm12 = (cast(uint)offset >> scale) & 0xFFF;
return ldst_pos(size,1,opc,imm12,Rn,Vt);

Check warning on line 975 in compiler/src/dmd/backend/arm/instr.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/instr.d#L971-L975

Added lines #L971 - L975 were not covered by tests
}

/* https://www.scs.stanford.edu/~zyedidia/arm64/ldr_imm_fpsimd.html
* LDR <Vt>,[<Xn|SP>,#<simm>] Unsigned offset
*/
static uint ldr_imm_fpsimd(uint size, uint opc, uint imm12, reg_t Rn, reg_t Vt) { return ldst_pos(size,1,opc,imm12,Rn,Vt); }
static uint ldr_imm_fpsimd(uint size, uint opc, uint offset, reg_t Rn, reg_t Vt)
{
assert(size < 4);
assert(opc < 4);
uint scale = ((opc & 2) << 1) | size;
uint imm12 = (cast(uint)offset >> scale) & 0xFFF;
return ldst_pos(size,1,opc,imm12,Rn,Vt);

Check warning on line 987 in compiler/src/dmd/backend/arm/instr.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/arm/instr.d#L983-L987

Added lines #L983 - L987 were not covered by tests
}

/* } */

Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dmd/backend/elfobj.d
Original file line number Diff line number Diff line change
Expand Up @@ -3340,7 +3340,9 @@ static if (0)
outrel:
//printf("\t\t************* adding relocation\n");
const size_t nbytes = ElfObj_writerel(seg, cast(uint)offset, relinfo, refseg, val);
assert(nbytes == refSize);
// nbytes is 4, refSize is 8, do not know which is correct TODO
//printf("nbytes: %lld refSize: %d\n", nbytes, refSize);
// assert(nbytes == refSize);
}
}
break;
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dmd/backend/x86/cod3.d
Original file line number Diff line number Diff line change
Expand Up @@ -3972,6 +3972,9 @@
@trusted
void prolog_genvarargs(ref CGstate cg, ref CodeBuilder cdb, Symbol* sv)
{
if (cg.AArch64)
return dmd.backend.arm.cod3.prolog_genvarargs(cg, cdb, sv);

Check warning on line 3976 in compiler/src/dmd/backend/x86/cod3.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/backend/x86/cod3.d#L3975-L3976

Added lines #L3975 - L3976 were not covered by tests

/* Generate code to move any arguments passed in registers into
* the stack variable __va_argsave,
* so we can reference it via pointers through va_arg().
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dmd/glue.d
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,9 @@
if ((target.isX86_64 || target.isAArch64) &&
target.os & Target.OS.Posix)
{
type* t = type_struct_class("__va_argsave_t", 16, 8 * 6 + 8 * 16 + 8 * 3 + 8, null, null, false, false, true, false);
type* t = target.isX86_64
? type_struct_class("__va_argsave_t", 16, 8 * 6 + 8 * 16 + 8 * 3 + 8, null, null, false, false, true, false)
: type_struct_class("__va_argsave_t", 16, 8 * 8 + 6 * 16, null, null, false, false, true, false);

Check warning on line 803 in compiler/src/dmd/glue.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/glue.d#L801-L803

Added lines #L801 - L803 were not covered by tests
// The backend will pick this up by name
Symbol* sv = symbol_name("__va_argsave", SC.auto_, t);
sv.Stype.Tty |= mTYvolatile;
Expand Down
Loading