diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h index 5fd364a25acdb4dfe1bec890e88013fc86318cc3..9d33c1e5771109b1e56b1dcd17e9523246f36016 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_cgfunc.h @@ -590,6 +590,8 @@ class AArch64CGFunc : public CGFunc { PrimType stype); bool GenerateCompareWithZeroInstruction(Opcode jmpOp, Opcode cmpOp, bool is64Bits, LabelOperand &targetOpnd, Operand &opnd0); + void GenCVaStartIntrin(RegOperand &opnd, uint32 stkSize); + void SelectCVaStart(IntrinsiccallNode &intrnNode); void SelectMPLClinitCheck(IntrinsiccallNode&); void SelectMPLProfCounterInc(IntrinsiccallNode &intrnNode); /* Helper functions for translating complex Maple IR instructions/inrinsics */ diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index fb7131985ad1b3d810a59b82455efac76af979fb..426ef3621521c9de9a05df90043e0ab39b6e6fcb 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -6255,6 +6255,92 @@ void AArch64CGFunc::SelectMPLClinitCheck(IntrinsiccallNode &intrnNode) { } } +void AArch64CGFunc::GenCVaStartIntrin(RegOperand &opnd, uint32 stkSize) { + // FPLR only pushed in regalloc() after intrin function + Operand &stkOpnd = GetOrCreatePhysicalRegisterOperand(RFP, k64BitSize, kRegTyInt); + + // __stack + AArch64ImmOperand *offsOpnd = &CreateImmOperand(0, k64BitSize, true, kUnAdjustVary); // isvary reset StackFrameSize + AArch64ImmOperand *offsOpnd2 = &CreateImmOperand(stkSize, k64BitSize, false); + RegOperand &vReg = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, GetPrimTypeSize(PTY_a64))); + if (stkSize) { + SelectAdd(vReg, *offsOpnd, *offsOpnd2, PTY_a64); + SelectAdd(vReg, stkOpnd, vReg, PTY_a64); + } else { + SelectAdd(vReg, stkOpnd, *offsOpnd, PTY_a64); + } + AArch64OfstOperand *offOpnd = &GetOrCreateOfstOpnd(0, k64BitSize); + MemOperand *strOpnd = &GetOrCreateMemOpnd(AArch64MemOperand::kAddrModeBOi, k64BitSize, &opnd, nullptr, + offOpnd, static_cast(nullptr)); // mem operand in va_list struct (lhs) + GetCurBB()->AppendInsn(GetCG()->BuildInstruction(MOP_xstr, vReg, *strOpnd)); + + // __gr_top ; it's the same as __stack before the 1st va_arg + offOpnd = &GetOrCreateOfstOpnd(k8BitSize, k64BitSize); + strOpnd = &GetOrCreateMemOpnd(AArch64MemOperand::kAddrModeBOi, k64BitSize, &opnd, nullptr, + offOpnd, static_cast(nullptr)); + SelectAdd(vReg, stkOpnd, *offsOpnd, PTY_a64); + GetCurBB()->AppendInsn(GetCG()->BuildInstruction(MOP_xstr, vReg, *strOpnd)); + + // __vr_top + int32 grAreaSize = static_cast(GetMemlayout())->GetSizeOfGRSaveArea(); + offsOpnd2 = &CreateImmOperand(RoundUp(grAreaSize, kSizeOfPtr*2), k64BitSize, false); + SelectSub(vReg, *offsOpnd, *offsOpnd2, PTY_a64); // if 1st opnd is register => sub + SelectAdd(vReg, stkOpnd, vReg, PTY_a64); + offOpnd = &GetOrCreateOfstOpnd(k16BitSize, k64BitSize); + strOpnd = &GetOrCreateMemOpnd(AArch64MemOperand::kAddrModeBOi, k64BitSize, &opnd, nullptr, + offOpnd, static_cast(nullptr)); + GetCurBB()->AppendInsn(GetCG()->BuildInstruction(MOP_xstr, vReg, *strOpnd)); + + // __gr_offs + int32 offs = 0 - grAreaSize; + offsOpnd = &CreateImmOperand(offs, k32BitSize, false); + RegOperand *tmpReg = &CreateRegisterOperandOfType(PTY_i32); // offs value to be assigned (rhs) + SelectCopyImm(*tmpReg, *offsOpnd, PTY_i32); + offOpnd = &GetOrCreateOfstOpnd(3*kSizeOfPtr, k32BitSize); + strOpnd = &GetOrCreateMemOpnd(AArch64MemOperand::kAddrModeBOi, k32BitSize, &opnd, nullptr, + offOpnd, static_cast(nullptr)); + GetCurBB()->AppendInsn(GetCG()->BuildInstruction(MOP_wstr, *tmpReg, *strOpnd)); + + // __vr_offs + offs = 0 - static_cast(GetMemlayout())->GetSizeOfVRSaveArea(); + offsOpnd = &CreateImmOperand(offs, k32BitSize, false); + tmpReg = &CreateRegisterOperandOfType(PTY_i32); + SelectCopyImm(*tmpReg, *offsOpnd, PTY_i32); + offOpnd = &GetOrCreateOfstOpnd(3*kSizeOfPtr+sizeof(int32), k32BitSize); + strOpnd = &GetOrCreateMemOpnd(AArch64MemOperand::kAddrModeBOi, k32BitSize, &opnd, nullptr, + offOpnd, static_cast(nullptr)); + GetCurBB()->AppendInsn(GetCG()->BuildInstruction(MOP_wstr, *tmpReg, *strOpnd)); +} + +void AArch64CGFunc::SelectCVaStart(IntrinsiccallNode &intrnNode) { + ASSERT(intrnNode.NumOpnds() == 2, "must be 2 operands"); + // 2 operands, but only 1 needed. Don't need to emit code for second operand + + // va_list is a passed struct with an address, load its address + BaseNode *argExpr = intrnNode.Opnd(0); + Operand *opnd = HandleExpr(intrnNode, *argExpr); + RegOperand &opnd0 = LoadIntoRegister(*opnd, PTY_a64); // first argument of intrinsic + + // Find beginning of unnamed arg on stack. + // Ex. void foo(int i1, int i2, ... int i8, struct S r, struct S s, ...) + // where struct S has size 32, address of r and s are on stack but they are named. + ParmLocator parmLocator(GetBecommon()); + PLocInfo pLoc; + uint32 stkSize = 0; + for (uint32 i = 0; i < GetFunction().GetFormalCount(); i++) { + MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(GetFunction().GetNthParamTyIdx(i)); + parmLocator.LocateNextParm(*ty, pLoc); + if (pLoc.reg0 == kRinvalid) { // on stack + stkSize = pLoc.memOffset + pLoc.memSize; + } + } + stkSize = RoundUp(stkSize, kSizeOfPtr); + + GenCVaStartIntrin(opnd0, stkSize); + + return; +} + void AArch64CGFunc::SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) { MIRIntrinsicID intrinsic = intrinsiccallNode.GetIntrinsic(); @@ -6283,6 +6369,10 @@ void AArch64CGFunc::SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) { (intrinsic == INTRN_MPL_CLEANUP_NORETESCOBJS)) { return; } + if (intrinsic == INTRN_C_va_start) { + SelectCVaStart(intrinsiccallNode); + return; + } std::vector operands; /* Temporary. Deallocated on return. */ AArch64ListOperand *srcOpnds = memPool->New(*GetFuncScopeAllocator()); for (size_t i = 0; i < intrinsiccallNode.NumOpnds(); i++) { diff --git a/src/mapleall/maple_ir/include/intrinsic_c.def b/src/mapleall/maple_ir/include/intrinsic_c.def index 5c5b9016893e81e0ab21a57d4ef85be2aa8a276a..1f0fd625d4a899725a8b9205c9c647fcc2a16686 100644 --- a/src/mapleall/maple_ir/include/intrinsic_c.def +++ b/src/mapleall/maple_ir/include/intrinsic_c.def @@ -76,7 +76,7 @@ DEF_MIR_INTRINSIC(C_sinh,\ DEF_MIR_INTRINSIC(C_ffs,\ "ffs", INTRNISPURE, kArgTyI32, kArgTyI32) DEF_MIR_INTRINSIC(C_va_start,\ - "sinh"/*dummy*/, INTRNISPURE, kArgTyVoid, kArgTyPtr, kArgTyI32) + "sinh"/*dummy*/, INTRNISPURE | INTRNISSPECIAL, kArgTyVoid, kArgTyPtr, kArgTyI32) DEF_MIR_INTRINSIC(C_constant_p,\ "sinh"/*dummy*/, 0, kArgTyI32, kArgTyDynany) DEF_MIR_INTRINSIC(C_clz32,\ @@ -86,4 +86,4 @@ DEF_MIR_INTRINSIC(C_clz64,\ DEF_MIR_INTRINSIC(C_ctz32,\ "sinh"/*dummy*/, INTRNISPURE, kArgTyI32, kArgTyU32) DEF_MIR_INTRINSIC(C_ctz64,\ - "sinh"/*dummy*/, INTRNISPURE, kArgTyI32, kArgTyU64) \ No newline at end of file + "sinh"/*dummy*/, INTRNISPURE, kArgTyI32, kArgTyU64)