diff --git a/src/mapleall/maple_be/include/be/becommon.h b/src/mapleall/maple_be/include/be/becommon.h index ccfd4c59a4d0bafc7659f320e6292dce23caaa77..954a35a0ef3eca991ed083230fa7d0c9731e72e7 100644 --- a/src/mapleall/maple_be/include/be/becommon.h +++ b/src/mapleall/maple_be/include/be/becommon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -114,6 +114,16 @@ class BECommon { void AddElementToJClassLayout(MIRClassType &klass, JClassFieldInfo info); + bool HasFuncReturnType(MIRFunction &func) const { + return (funcReturnType.find(&func) != funcReturnType.end()); + } + + const TyIdx GetFuncReturnType(MIRFunction &func) const { + return (funcReturnType.at(&func)); + } + + void AddElementToFuncReturnType(MIRFunction &func, TyIdx tyIdx); + MIRType *BeGetOrCreatePointerType(const MIRType &pointedType); MIRType *BeGetOrCreateFunctionType(TyIdx tyIdx, const std::vector &vecTy, @@ -223,6 +233,7 @@ class BECommon { * Note: currently only for java class types. */ MapleUnorderedMap jClassLayoutTable; + MapleUnorderedMap funcReturnType; }; /* class BECommon */ } /* namespace maplebe */ diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_memlayout.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_memlayout.h index c05a3d0fcb116cf0329b0c372f510ed35fcb3125..d4bfa3a21a0665326a3efee8c405ab56232602f4 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_memlayout.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_memlayout.h @@ -163,19 +163,40 @@ class AArch64MemLayout : public MemLayout { return segLocals.GetSize(); } + void SetSizeOfGRSaveArea(int32 sz) { + segGrSaveArea.SetSize(sz); + } + + int32 GetSizeOfGRSaveArea() { + return segGrSaveArea.GetSize(); + } + + inline void SetSizeOfVRSaveArea(int32 sz) { + segVrSaveArea.SetSize(sz); + } + + int32 GetSizeOfVRSaveArea() { + return segVrSaveArea.GetSize(); + } + int32 GetSizeOfRefLocals() { return segRefLocals.GetSize(); } int32 GetRefLocBaseLoc() const; + int32 GetGRSaveAreaBaseLoc(); + int32 GetVRSaveAreaBaseLoc(); private: MemSegment segRefLocals = MemSegment(kMsRefLocals); /* callee saved register R19-R28 (10) */ MemSegment segSpillReg = MemSegment(kMsSpillReg); MemSegment segLocals = MemSegment(kMsLocals); /* these are accessed via Frame Pointer */ + MemSegment segGrSaveArea = MemSegment(kMsGrSaveArea); + MemSegment segVrSaveArea = MemSegment(kMsVrSaveArea); int32 fixStackSize = 0; void SetSegmentSize(AArch64SymbolAlloc &symbolAlloc, MemSegment &segment, uint32 typeIdx); + void LayoutVarargParams(); void LayoutFormalParams(); void LayoutActualParams(); void LayoutLocalVariales(std::vector &tempVar, std::vector &returnDelays); diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_proepilog.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_proepilog.h index cff964d49928d44d687972bf058d8d8c3fb5f5c6..fa9074fe1769adcbe8d44c4125b1a6297a36e2f2 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_proepilog.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_proepilog.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -41,6 +41,7 @@ class AArch64GenProEpilog : public GenProEpilog { void AppendInstructionAllocateCallFrame(AArch64reg reg0, AArch64reg reg1, RegType rty); void AppendInstructionAllocateCallFrameDebug(AArch64reg reg0, AArch64reg reg1, RegType rty); void GeneratePushRegs(); + void GeneratePushUnnamedVarargRegs(); void AppendInstructionStackCheck(AArch64reg reg, RegType rty, int offset); void GenerateProlog(BB&); diff --git a/src/mapleall/maple_be/include/cg/memlayout.h b/src/mapleall/maple_be/include/cg/memlayout.h index e6bdc8f6c20a207785dad56e85ca33ac658eaafd..018150e8508dca936b67fac0f77c2ac9c77a338d 100644 --- a/src/mapleall/maple_be/include/cg/memlayout.h +++ b/src/mapleall/maple_be/include/cg/memlayout.h @@ -47,6 +47,11 @@ enum MemSegmentKind : uint8 { * (or we may allocate them in caller-saved; may be this is better...) */ kMsArgsRegPassed, + /* + * GR/VR Save areas for unnamed arguments under vararg functions + */ + kMsGrSaveArea, + kMsVrSaveArea, /* local (auto) variables */ kMsRefLocals, kMsLocals, diff --git a/src/mapleall/maple_be/src/be/becommon.cpp b/src/mapleall/maple_be/src/be/becommon.cpp index 4ec0ff9b760d0b21d0a3ae3b788b6c5c8c321d55..e0036a1e14e2424840948bc15b11be87794b95d7 100644 --- a/src/mapleall/maple_be/src/be/becommon.cpp +++ b/src/mapleall/maple_be/src/be/becommon.cpp @@ -30,7 +30,8 @@ BECommon::BECommon(MIRModule &mod) mirModule.GetMPAllocator().Adapter()), structFieldCountTable(GlobalTables::GetTypeTable().GetTypeTable().size(), 0, mirModule.GetMPAllocator().Adapter()), - jClassLayoutTable(mirModule.GetMPAllocator().Adapter()) { + jClassLayoutTable(mirModule.GetMPAllocator().Adapter()), + funcReturnType(mirModule.GetMPAllocator().Adapter()) { for (uint32 i = 1; i < GlobalTables::GetTypeTable().GetTypeTable().size(); ++i) { MIRType *ty = GlobalTables::GetTypeTable().GetTypeTable()[i]; ComputeTypeSizesAligns(*ty); @@ -600,6 +601,11 @@ void BECommon::AddElementToJClassLayout(MIRClassType &klass, JClassFieldInfo inf layout.emplace_back(info); } +void BECommon::AddElementToFuncReturnType(MIRFunction &func, TyIdx tyIdx) { + TyIdx &ty = funcReturnType.at(&func); + ty = tyIdx; +} + MIRType *BECommon::BeGetOrCreatePointerType(const MIRType &pointedType) { MIRType *newType = GlobalTables::GetTypeTable().GetOrCreatePointerType(pointedType, PTY_a64); if (TyIsInSizeAlignTable(*newType)) { diff --git a/src/mapleall/maple_be/src/be/lower.cpp b/src/mapleall/maple_be/src/be/lower.cpp index c5927960f6666a50f40c5f50ec723514ef0621f7..db9ef265a9002138d1914ba4479dfb64258bdbb3 100644 --- a/src/mapleall/maple_be/src/be/lower.cpp +++ b/src/mapleall/maple_be/src/be/lower.cpp @@ -1242,6 +1242,8 @@ void CGLowerer::LowerEntry(MIRFunction &func) { formals.emplace_back(formal); } + beCommon.AddElementToFuncReturnType(func, func.GetReturnTyIdx()); + func.UpdateFuncTypeAndFormalsAndReturnType(formals, TyIdx(PTY_void), true); auto *funcType = func.GetMIRFuncType(); ASSERT(funcType != nullptr, "null ptr check"); diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp index da1036253f3bbfbb0af39e6ff98a47e7b7bbb30d..d1bfbb382f1d84dc87bf8cd39d927b487805b151 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_memlayout.cpp @@ -104,6 +104,44 @@ void AArch64MemLayout::SetSegmentSize(AArch64SymbolAlloc &symbolAlloc, MemSegmen segment.SetSize(static_cast(RoundUp(static_cast(segment.GetSize()), kSizeOfPtr))); } +void AArch64MemLayout::LayoutVarargParams() { + uint32 nIntRegs = 0; + uint32 nFpRegs = 0; + ParmLocator parmlocator(be); + PLocInfo ploc; + MIRFunction *func = mirFunction; + if (be.GetMIRModule().IsCModule() && func->GetAttr(FUNCATTR_varargs)) { + for (uint32 i = 0; i < func->GetFormalCount(); i++) { + if (i == 0) { + if (be.HasFuncReturnType(*func)) { + TyIdx tidx = be.GetFuncReturnType(*func); + if (be.GetTypeSize(tidx.GetIdx()) <= 16) { + continue; + } + } + } + MIRType *ty = func->GetNthParamType(i); + parmlocator.LocateNextParm(*ty, ploc); + if (ploc.reg0 != kRinvalid) { + if (ploc.reg0 >= R0 && ploc.reg0 <= R7) { + nIntRegs++; + } else if (ploc.reg0 >= V0 && ploc.reg0 <= V7) { + nFpRegs++; + } + } + if (ploc.reg1 != kRinvalid) { + if (ploc.reg1 >= R0 && ploc.reg1 <= R7) { + nIntRegs++; + } else if (ploc.reg1 >= V0 && ploc.reg1 <= V7) { + nFpRegs++; + } + } + } + SetSizeOfGRSaveArea((k8BitSize - nIntRegs) * kSizeOfPtr); + SetSizeOfVRSaveArea((k8BitSize - nFpRegs) * kSizeOfPtr * 2); + } +} + void AArch64MemLayout::LayoutFormalParams() { ParmLocator parmLocator(be); PLocInfo ploc; @@ -260,6 +298,7 @@ void AArch64MemLayout::LayoutActualParams() { } void AArch64MemLayout::LayoutStackFrame(int32 &structCopySize, int32 &maxParmStackSize) { + LayoutVarargParams(); LayoutFormalParams(); /* * We do need this as LDR/STR with immediate @@ -337,6 +376,13 @@ int32 AArch64MemLayout::StackFrameSize() { int32 total = segArgsRegPassed.GetSize() + static_cast(cgFunc)->SizeOfCalleeSaved() + GetSizeOfRefLocals() + locals().GetSize() + GetSizeOfSpillReg(); + if (GetSizeOfGRSaveArea() > 0) { + total += RoundUp(GetSizeOfGRSaveArea(), kAarch64StackPtrAlignment); + } + if (GetSizeOfVRSaveArea() > 0) { + total += RoundUp(GetSizeOfVRSaveArea(), kAarch64StackPtrAlignment); + } + /* * if the function does not have VLA nor alloca, * we allocate space for arguments to stack-pass @@ -362,4 +408,20 @@ int32 AArch64MemLayout::GetRefLocBaseLoc() const { } return beforeSize + kSizeOfFplr; } + +int32 AArch64MemLayout::GetGRSaveAreaBaseLoc() { + int32 total = RealStackFrameSize() - + RoundUp(GetSizeOfGRSaveArea(), kAarch64StackPtrAlignment); + total -= SizeOfArgsToStackPass(); + return total; +} + +int32 AArch64MemLayout::GetVRSaveAreaBaseLoc() { + int32 total = RealStackFrameSize() - + RoundUp(GetSizeOfGRSaveArea(), kAarch64StackPtrAlignment) - + RoundUp(GetSizeOfVRSaveArea(), kAarch64StackPtrAlignment); + total -= SizeOfArgsToStackPass(); + return total; +} + } /* namespace maplebe */ diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp index 9d75ba6f4834571126d4a37b2b46a417bbee6ae6..8f2ddb4a5bd409663e5caad2aed9a1e58848aadb 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_proepilog.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -86,10 +86,21 @@ void AArch64GenProEpilog::GenStackGuard(BB &bb) { insn.SetDoNotRemove(true); cgFunc.GetCurBB()->AppendInsn(insn); + int vArea = 0; + if (cgFunc.GetMirModule().IsCModule() && cgFunc.GetFunction().GetAttr(FUNCATTR_varargs)) { + AArch64MemLayout *ml = static_cast(cgFunc.GetMemlayout()); + if (ml->GetSizeOfGRSaveArea() > 0) { + vArea += RoundUp(ml->GetSizeOfGRSaveArea(), kAarch64StackPtrAlignment); + } + if (ml->GetSizeOfVRSaveArea() > 0) { + vArea += RoundUp(ml->GetSizeOfVRSaveArea(), kAarch64StackPtrAlignment); + } + } + int32 stkSize = static_cast(cgFunc.GetMemlayout())->RealStackFrameSize() - - static_cast(cgFunc.GetMemlayout())->SizeOfArgsToStackPass(); - AArch64MemOperand *downStk = aarchCGFunc.GetMemoryPool()->New(RFP, stkSize - kOffset8MemPos, - kSizeOfPtr * kBitsPerByte); + static_cast(cgFunc.GetMemlayout())->SizeOfArgsToStackPass() - vArea; + AArch64MemOperand *downStk = aarchCGFunc.GetMemoryPool()->New(RFP, + stkSize - kOffset8MemPos - vArea, kSizeOfPtr * kBitsPerByte); if (downStk->GetMemVaryType() == kNotVary && aarchCGFunc.IsImmediateOffsetOutOfRange(*downStk, k64BitSize)) { downStk = &aarchCGFunc.SplitOffsetWithAddInstruction(*downStk, k64BitSize, R10); @@ -133,12 +144,23 @@ BB &AArch64GenProEpilog::GenStackGuardCheckInsn(BB &bb) { insn.SetDoNotRemove(true); cgFunc.GetCurBB()->AppendInsn(insn); + int vArea = 0; + if (cgFunc.GetMirModule().IsCModule() && cgFunc.GetFunction().GetAttr(FUNCATTR_varargs)) { + AArch64MemLayout *ml = static_cast(cgFunc.GetMemlayout()); + if (ml->GetSizeOfGRSaveArea() > 0) { + vArea += RoundUp(ml->GetSizeOfGRSaveArea(), kAarch64StackPtrAlignment); + } + if (ml->GetSizeOfVRSaveArea() > 0) { + vArea += RoundUp(ml->GetSizeOfVRSaveArea(), kAarch64StackPtrAlignment); + } + } + AArch64RegOperand &checkOp = aarchCGFunc.GetOrCreatePhysicalRegisterOperand(R10, kSizeOfPtr * kBitsPerByte, kRegTyInt); int32 stkSize = static_cast(cgFunc.GetMemlayout())->RealStackFrameSize() - - static_cast(cgFunc.GetMemlayout())->SizeOfArgsToStackPass(); - AArch64MemOperand *downStk = aarchCGFunc.GetMemoryPool()->New(RFP, stkSize - kOffset8MemPos, - kSizeOfPtr * kBitsPerByte); + static_cast(cgFunc.GetMemlayout())->SizeOfArgsToStackPass() - vArea; + AArch64MemOperand *downStk = aarchCGFunc.GetMemoryPool()->New + (RFP, stkSize - kOffset8MemPos - vArea, kSizeOfPtr * kBitsPerByte); if (downStk->GetMemVaryType() == kNotVary && aarchCGFunc.IsImmediateOffsetOutOfRange(*downStk, k64BitSize)) { downStk = &aarchCGFunc.SplitOffsetWithAddInstruction(*static_cast(downStk), k64BitSize, R10); } @@ -550,6 +572,14 @@ void AArch64GenProEpilog::GeneratePushRegs() { (aarchCGFunc.SizeOfCalleeSaved() - (kDivide2 * kIntregBytelen) /* for FP/LR */) - cgFunc.GetMemlayout()->SizeOfArgsToStackPass(); + if (cgFunc.GetMirModule().IsCModule() && cgFunc.GetFunction().GetAttr(FUNCATTR_varargs)) { + // GR/VR save areas are above the callee save area + AArch64MemLayout *ml = static_cast(cgFunc.GetMemlayout()); + int saveareasize = RoundUp(ml->GetSizeOfGRSaveArea(), kSizeOfPtr*2) + + RoundUp(ml->GetSizeOfVRSaveArea(), kSizeOfPtr*2); + offset -= saveareasize; + } + for (; it != regsToSave.end(); ++it) { AArch64reg reg = *it; CHECK_FATAL(reg != RFP, "stray RFP in callee_saved_list?"); @@ -585,6 +615,40 @@ void AArch64GenProEpilog::GeneratePushRegs() { aarchCGFunc.SetSplitBaseOffset(0); } +void AArch64GenProEpilog::GeneratePushUnnamedVarargRegs() { + auto &aarchCGFunc = static_cast(cgFunc); + CG *currCG = cgFunc.GetCG(); + if (cgFunc.GetMirModule().IsCModule() && cgFunc.GetFunction().GetAttr(FUNCATTR_varargs)) { + AArch64MemLayout *memlayout = static_cast(cgFunc.GetMemlayout()); + uint32 dataSizeBits = kSizeOfPtr * kBitsPerByte; + int32 offset = memlayout->GetGRSaveAreaBaseLoc(); + if (memlayout->GetSizeOfGRSaveArea() % kAarch64StackPtrAlignment) { + offset += kSizeOfPtr; // End of area should be aligned. Hole between VR and GR area + } + int32 start_regno = 8 - (memlayout->GetSizeOfGRSaveArea() / kSizeOfPtr); + ASSERT(start_regno <= 8, "Incorrect starting GR regno for GR Save Area"); + for (uint32 i = start_regno + (uint32)R0; i < (uint32)R8; i++) { + Operand &stackloc = aarchCGFunc.CreateStkTopOpnd(offset, dataSizeBits); + RegOperand ® = aarchCGFunc.GetOrCreatePhysicalRegisterOperand((AArch64reg)i, 64, kRegTyInt); + Insn &inst = currCG->BuildInstruction( + aarchCGFunc.PickStInsn(dataSizeBits, PTY_i64), reg, stackloc); + cgFunc.GetCurBB()->AppendInsn(inst); + offset += kSizeOfPtr; + } + offset = memlayout->GetVRSaveAreaBaseLoc(); + start_regno = 8 - (memlayout->GetSizeOfVRSaveArea() / (kSizeOfPtr * 2)); + ASSERT(start_regno <= 8, "Incorrect starting GR regno for VR Save Area"); + for (uint32 i = start_regno + (uint32)V0; i < (uint32)V8; i++) { + Operand &stackloc = aarchCGFunc.CreateStkTopOpnd(offset, dataSizeBits); + RegOperand ® = aarchCGFunc.GetOrCreatePhysicalRegisterOperand((AArch64reg)i, 64, kRegTyInt); + Insn &inst = currCG->BuildInstruction( + aarchCGFunc.PickStInsn(dataSizeBits, PTY_i64), reg, stackloc); + cgFunc.GetCurBB()->AppendInsn(inst); + offset += (kSizeOfPtr * 2); + } + } +} + void AArch64GenProEpilog::AppendInstructionStackCheck(AArch64reg reg, RegType rty, int32 offset) { auto &aarchCGFunc = static_cast(cgFunc); CG *currCG = cgFunc.GetCG(); @@ -658,6 +722,7 @@ void AArch64GenProEpilog::GenerateProlog(BB &bb) { aarchCGFunc.CreateCfiRegOperand(RFP, k64BitSize))); } } + GeneratePushUnnamedVarargRegs(); if (currCG->DoCheckSOE()) { AppendInstructionStackCheck(R16, kRegTyInt, kSoeChckOffset); } @@ -676,6 +741,12 @@ void AArch64GenProEpilog::GenerateRet(BB &bb) { * Otherwise, return false, create the ret insn. */ bool AArch64GenProEpilog::TestPredsOfRetBB(const BB &exitBB) { + AArch64MemLayout *ml = static_cast(cgFunc.GetMemlayout()); + if (cgFunc.GetMirModule().IsCModule() && + (cgFunc.GetFunction().GetAttr(FUNCATTR_varargs) || + ml->GetSizeOfLocals() > 0 || cgFunc.HasVLAOrAlloca())) { + return false; + } for (auto tmpBB : exitBB.GetPreds()) { Insn *firstInsn = tmpBB->GetFirstInsn(); if ((firstInsn == nullptr || tmpBB->IsCommentBB()) && (!tmpBB->GetPreds().empty())) { @@ -884,6 +955,14 @@ void AArch64GenProEpilog::GeneratePopRegs() { (aarchCGFunc.SizeOfCalleeSaved() - (kDivide2 * kIntregBytelen) /* for FP/LR */) - cgFunc.GetMemlayout()->SizeOfArgsToStackPass(); + if (cgFunc.GetMirModule().IsCModule() && cgFunc.GetFunction().GetAttr(FUNCATTR_varargs)) { + // GR/VR save areas are above the callee save area + AArch64MemLayout *ml = static_cast(cgFunc.GetMemlayout()); + int saveareasize = RoundUp(ml->GetSizeOfGRSaveArea(), kSizeOfPtr*2) + + RoundUp(ml->GetSizeOfVRSaveArea(), kSizeOfPtr*2); + offset -= saveareasize; + } + /* * We are using a cleared dummy block; so insertPoint cannot be ret; * see GenerateEpilog() diff --git a/src/mapleall/maple_ir/src/mir_module.cpp b/src/mapleall/maple_ir/src/mir_module.cpp index fb3f815f6fc1fa4dba9577b35a5ff46b94324e07..4efa53ac49a61231c910e6cdd522d49f0f41dbc6 100644 --- a/src/mapleall/maple_ir/src/mir_module.cpp +++ b/src/mapleall/maple_ir/src/mir_module.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2021] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -505,8 +505,14 @@ std::string MIRModule::GetFileNameAsPostfix() const { fileNameStr += GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(fileNameIdx)); } else { // option 2: src file name removing ext name. - ASSERT(fileNameStr.find_last_of('.') != fileNameStr.npos, "not found."); - fileNameStr += fileNameStr.substr(0, fileNameStr.find_last_of('.')); + if (GetSrcFileInfo().size() != 0) { + GStrIdx idx = GetSrcFileInfo()[0].first; + const std::string kStr = GlobalTables::GetStrTable().GetStringFromStrIdx(idx); + ASSERT(kStr.find_last_of('.') != kStr.npos, "not found ."); + fileNameStr += kStr.substr(0, kStr.find_last_of('.')); + } else { + ASSERT(0, "No fileinfo and no srcfileinfo in mpl file"); + } } for (char &c : fileNameStr) { if (!isalpha(c) && !isdigit(c) && c != '_' && c != '$') {