diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h index 958c5b9625c2df8cb550c7d80b36f2a87a785d68..4846a4cb9c991c1d4984cb2a8fc888b65b436969 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -93,6 +93,19 @@ template <> struct ilist_callback_traits { /// of type are accessed/created with MF::getInfo and destroyed when the /// MachineFunction is destroyed. struct MachineFunctionInfo { + +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL begin + struct ArkArgInfo { + int64_t MemOffset; + Register Reg; + int32_t OriginIndex; + ArkArgInfo(int64_t MemOffset, Register Reg, int32_t OriginIndex) + : MemOffset(MemOffset), Reg(Reg), OriginIndex(OriginIndex) {} + }; + // OHOS_LOCAL end +#endif + virtual ~MachineFunctionInfo(); /// Factory function: default behavior is to call new using the diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h index 2e96fcd0415dce5d7ed5bf63c7e01f96bc15a18b..5ac6ee4dd0aa26731be16db9770818fbe760aca1 100644 --- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -306,6 +306,15 @@ public: virtual int getArkFrameAdaptationOffset(const MachineFunction &MF) const { return 0; } + +#ifdef ARK_GC_SUPPORT + virtual void adjustForArkFrame(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const {} + static const std::string TypeKey; + static const std::string JSFuncIdxKey; + static const std::string TypeOffsetKey; + static const std::string JSFuncIdxOffsetKey; +#endif // OHOS_LOCAL end /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index 5dbcd0facfd15df3f93b5923e1f015013c1c1c5f..441523c3b8790c0231c18888d07458edcd281c70 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -1405,6 +1405,16 @@ void PEI::insertPrologEpilogCode(MachineFunction &MF) { for (MachineBasicBlock *SaveBlock : SaveBlocks) TFI.adjustForSegmentedStacks(MF, *SaveBlock); } + // OHOS_LOCAL begin +#ifdef ARK_GC_SUPPORT + // Insert the prologue to save ark-frame-type + if (MF.getFunction().hasFnAttribute(TargetFrameLowering::TypeKey) || + MF.getFunction().hasFnAttribute(TargetFrameLowering::JSFuncIdxKey)) { + for (MachineBasicBlock *SaveBlock : SaveBlocks) + TFI.adjustForArkFrame(MF, *SaveBlock); + } +#endif + // OHOS_LOCAL end // Emit additional code that is required to explicitly handle the stack in // HiPE native code (if needed) when loaded in the Erlang/OTP runtime. The diff --git a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp index 0e026bdf42f12e902b26ca7c0a53d4a9bf7a3d8e..ef8261e845fb535b5878c672178f67bd857a9fe5 100644 --- a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp +++ b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp @@ -181,6 +181,7 @@ TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const { } #ifdef ARK_GC_SUPPORT +// OHOS_LOCAL begin int TargetFrameLowering::GetFrameReserveSize(MachineFunction &MF) const { int slotSize = sizeof(uint64_t); @@ -192,4 +193,11 @@ int TargetFrameLowering::GetFrameReserveSize(MachineFunction &MF) const .getAsInteger(10, marker); return marker; } + +const std::string TargetFrameLowering::TypeKey = "ark-frame-type"; +const std::string TargetFrameLowering::JSFuncIdxKey = "ark-jsfunc-arg-idx"; +const std::string TargetFrameLowering::TypeOffsetKey = TypeKey + "-offset"; +const std::string TargetFrameLowering::JSFuncIdxOffsetKey = + JSFuncIdxKey + "-offset"; +// OHOS_LOCAL end #endif diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 43ee70edcd2346fd76e5f85164a8fc163c3d13fa..a27de4b7d769a443988efd61f9b984e73dad1460 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -1656,6 +1656,18 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, assert(Prolog->getOpcode() == AArch64::HOM_Prolog); Prolog->addOperand(MachineOperand::CreateImm(FPOffset)); } else { +#ifdef ARK_GC_SUPPORT + if (!CombineSPBump) { + auto ReserveSize = alignTo(GetFrameReserveSize(MF), getStackAlign()); + emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP, + StackOffset::getFixed(-ReserveSize), TII, + MachineInstr::FrameSetup, false, NeedsWinCFI, + &HasWinCFI, EmitCFI, + StackOffset::getFixed(PrologueSaveSize)); + NumBytes -= ReserveSize; + FPOffset += ReserveSize; + } +#endif // Issue sub fp, sp, FPOffset or // mov fp,sp when FPOffset is zero. // Note: All stores of callee-saved registers are marked as "FrameSetup". @@ -4029,3 +4041,192 @@ void AArch64FrameLowering::orderFrameObjects( dbgs() << "\n"; }); } + +#ifdef ARK_GC_SUPPORT +// OHOS_LOCAL begin +namespace { +int64_t getStringAttrToInt(const Function &F, const StringRef Key) { + int64_t Value = 0; + bool Res = F.getFnAttribute(Key).getValueAsString().getAsInteger(10,Value); + assert(!Res && "Can get attribute to int"); + return Value; +} +} // namespace + +static bool useTempBaseRegisterIfNeed( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, const TargetInstrInfo *TII, unsigned Opcode, + int32_t MaxNeedOffset, int32_t &NewBaseOffset, Register &BaseReg) { + TypeSize Scale = TypeSize::Fixed(1); + unsigned Width; + int64_t MinOffset; + int64_t MaxOffset; + bool Res = AArch64InstrInfo::getMemOpInfo(Opcode, Scale, Width, MinOffset, + MaxOffset); + assert(Res && "Unsupported opcode"); + if (MaxNeedOffset > Scale * MaxOffset) { + auto NewBaseRegister = AArch64::X16; + emitFrameOffset(MBB, MBBI, DL, NewBaseRegister, BaseReg, + StackOffset::getFixed(NewBaseOffset), TII); + BaseReg = NewBaseRegister; + NewBaseOffset = 0; + return true; + } + return false; +} + +void AArch64FrameLowering::adjustForArkFrame( + MachineFunction &MF, MachineBasicBlock &PrologueMBB) const { + const auto &F = MF.getFunction(); + AArch64FunctionInfo *AFI = MF.getInfo(); + const MachineFrameInfo &MFI = MF.getFrameInfo(); + const AArch64InstrInfo *TII = + MF.getSubtarget().getInstrInfo(); + const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); + assert(F.hasFnAttribute("fpToCallerSpDelta") && "missing fpToCallerSpDelta"); + const StringRef FPToCallerSPDeltaStr = + F.getFnAttribute("fpToCallerSpDelta").getValueAsString(); + const int64_t FPToCallerSPDelta = std::stoi(FPToCallerSPDeltaStr.str()); + + MachineBasicBlock::iterator InsertPos; + // if CombineSPBump, the sp is updated once at the entry of the function. + // the frametype and jsfunc should be saved after sp is updated. + // if CombineSPBump is false, the sp is updated at least twice, the frametype + // and jsfunc should be saved before fp is updated. + bool CombineSPBump = shouldCombineCSRLocalStackBump(MF, MFI.getStackSize()); + Register DefineReg = CombineSPBump ? AArch64::SP : AArch64::FP; + for (auto &Iter : PrologueMBB) { + if (Iter.definesRegister(DefineReg, RegInfo)) { + InsertPos = Iter; + break; + } + } + if (CombineSPBump) { + // the InsertPos should be the position after sp update. + InsertPos = InsertPos->getNextNode(); + if (InsertPos->isCFIInstruction()) { + InsertPos = InsertPos->getNextNode(); + } + } + uint64_t ReserveSize = alignTo(GetFrameReserveSize(MF), getStackAlign()); + uint64_t SPOffset = + CombineSPBump ? MFI.getStackSize() : ReserveSize + FPToCallerSPDelta; + + assert(InsertPos.isValid() && InsertPos->isCFIInstruction() && + "Can't find the instruction to update fp"); + + DebugLoc DL = InsertPos->getDebugLoc(); + + struct SaveInfo { + bool NeedSave; + Register Reg; + int32_t Offset; + uint32_t RegState; + bool operator<(const SaveInfo &Other) const { + return this->Offset < Other.Offset; + } + }; + + SaveInfo FrameTypeInfo = SaveInfo{false, MCRegister::NoRegister, 0, 0}; + SaveInfo JSFuncArgInfo = SaveInfo{false, MCRegister::NoRegister, 0, 0}; + + if (F.hasFnAttribute(TypeKey)) { + assert(F.hasFnAttribute(TypeOffsetKey) && "missing ark-frame-type-offset"); + const int64_t ArkFrameType = getStringAttrToInt(F, TypeKey); + const int32_t FrameTypeOffset = getStringAttrToInt(F, TypeOffsetKey); + Register ScratchFrameTypeReg; + uint32_t Flags = 0; + if (ArkFrameType == 0) { + // ScratchFrameTypeReg is zxr + ScratchFrameTypeReg = AArch64::XZR; + } else { + // mov x8, #ArkFrameType + ScratchFrameTypeReg = AArch64::X8; + BuildMI(PrologueMBB, InsertPos, DL, TII->get(AArch64::MOVi64imm), + ScratchFrameTypeReg) + .addImm(ArkFrameType); + Flags = RegState::Kill; + // after store. x8 will not be used. So mark it kill. + } + FrameTypeInfo = SaveInfo{true, ScratchFrameTypeReg, FrameTypeOffset, Flags}; + } + + if (F.hasFnAttribute(JSFuncIdxKey)) { + assert(F.hasFnAttribute(JSFuncIdxOffsetKey) && + "missing ark-jsfunc-arg-idx-offset"); + const int64_t JSFuncIdx = getStringAttrToInt(F, JSFuncIdxKey); + const int32_t JSFuncOffset = getStringAttrToInt(F, JSFuncIdxOffsetKey); + using ArkArgInfo = MachineFunctionInfo::ArkArgInfo; + const ArkArgInfo *JSFuncArg = + llvm::find_if(AFI->getArkArgInfos(), [JSFuncIdx](const ArkArgInfo Arg) { + return Arg.OriginIndex == JSFuncIdx; + }); + + Register ScratchJSFuncReg; + unsigned Flags = 0; + if (JSFuncArg->Reg != MCRegister::NoRegister) { + // ScratchJSFuncReg is the JSFuncIdx arg register. + ScratchJSFuncReg = JSFuncArg->Reg; + } else { + Register TempSP = AArch64::SP; + int32_t ArgToTempSP = SPOffset + JSFuncArg->MemOffset; + useTempBaseRegisterIfNeed(PrologueMBB, InsertPos, DL, TII, + AArch64::LDRXui, ArgToTempSP, ArgToTempSP, + TempSP); + // ldr x9, [TempSP, #SPOffset+JSFuncArg->MemOffset] + ScratchJSFuncReg = AArch64::X9; + BuildMI(PrologueMBB, InsertPos, DL, TII->get(AArch64::LDRXui)) + .addDef(ScratchJSFuncReg) + .addUse(TempSP) + .addImm(ArgToTempSP / 8); + Flags = RegState::Kill; + // after store. x9 will not be used. So mark it kill. + } + JSFuncArgInfo = SaveInfo{true, ScratchJSFuncReg, JSFuncOffset, Flags}; + } + + const bool CanUseSTP = + (FrameTypeInfo.NeedSave && JSFuncArgInfo.NeedSave && + std::abs(FrameTypeInfo.Offset - JSFuncArgInfo.Offset) == 8); + // 8 bytes distance store can be combined to stp + + const int32_t MaxSaveOffset = + std::max(FrameTypeInfo.Offset, JSFuncArgInfo.Offset); + Register TempSP = AArch64::SP; + int32_t ArkSlotToTempSP = SPOffset - FPToCallerSPDelta - MaxSaveOffset; + int32_t MaxSaveSlotToTempSP = ArkSlotToTempSP + MaxSaveOffset; + + useTempBaseRegisterIfNeed(PrologueMBB, InsertPos, DL, TII, + CanUseSTP ? AArch64::STPXi : AArch64::STRXui, + CanUseSTP ? ArkSlotToTempSP : MaxSaveSlotToTempSP, + ArkSlotToTempSP, TempSP); + + if (CanUseSTP) { + auto Max = std::max(FrameTypeInfo, JSFuncArgInfo); + auto Min = std::min(FrameTypeInfo, JSFuncArgInfo); + // stp RegArg, x8, [TempSP, #ArkSlotToTempSP] + BuildMI(PrologueMBB, InsertPos, DL, TII->get(AArch64::STPXi)) + .addUse(Max.Reg, Max.RegState) + .addUse(Min.Reg, Min.RegState) + .addReg(TempSP) + .addImm(ArkSlotToTempSP / 8); + return; + } + + if (FrameTypeInfo.NeedSave) { + // stur x8, [TempSP, #(ArkSlotToTempSP+MaxSaveOffset-FrameTypeInfo.Offset)] + BuildMI(PrologueMBB, InsertPos, DL, TII->get(AArch64::STRXui)) + .addUse(FrameTypeInfo.Reg, FrameTypeInfo.RegState) + .addReg(TempSP) + .addImm((ArkSlotToTempSP + (MaxSaveOffset - FrameTypeInfo.Offset)) / 8); + } + if (JSFuncArgInfo.NeedSave) { + // stur x9, [TempSP, #(ArkSlotToTempSP+MaxSaveOffset-JSFuncArgInfo.Offset)] + BuildMI(PrologueMBB, InsertPos, DL, TII->get(AArch64::STRXui)) + .addUse(JSFuncArgInfo.Reg, JSFuncArgInfo.RegState) + .addReg(TempSP) + .addImm((ArkSlotToTempSP + (MaxSaveOffset - JSFuncArgInfo.Offset)) / 8); + } +} +// OHOS_LOCAL end +#endif diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.h b/llvm/lib/Target/AArch64/AArch64FrameLowering.h index 221f92856c5573367ba6d3abc4a2a5b667e2c9d9..91d399d4045733163f12e49404601dd1fadefd9b 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.h +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.h @@ -83,6 +83,11 @@ public: } int getArkFrameAdaptationOffset(const MachineFunction &MF) const override; + +#ifdef ARK_GC_SUPPORT + void adjustForArkFrame(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const override; +#endif // OHOS_LOCAL end bool hasFP(const MachineFunction &MF) const override; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index d742d87eca22abe737846dd3ce95b3a53d0fef7f..fa0dd4421823ae5b033960d716f6f916d4181c22 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -5916,6 +5916,11 @@ SDValue AArch64TargetLowering::LowerFormalArguments( ArgValue = DAG.getZExtOrTrunc(ArgValue, DL, VA.getValVT()); break; } +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL + // Record the register and index of every argument which in register. + FuncInfo->addArkArgInfo(0, VA.getLocReg(), Ins[i].getOrigArgIndex()); +#endif } else { // VA.isRegLoc() assert(VA.isMemLoc() && "CCValAssign is neither reg nor mem"); unsigned ArgOffset = VA.getLocMemOffset(); @@ -5963,6 +5968,13 @@ SDValue AArch64TargetLowering::LowerFormalArguments( ArgValue = DAG.getExtLoad(ExtType, DL, VA.getLocVT(), Chain, FIN, MachinePointerInfo::getFixedStack(MF, FI), MemVT); +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL + // Record the offset (relative to SP) and index of every argument which on + // stack. + FuncInfo->addArkArgInfo(VA.getLocMemOffset(), MCRegister::NoRegister, + Ins[i].getOrigArgIndex()); +#endif } if (VA.getLocInfo() == CCValAssign::Indirect) { diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h index c658f821464eeb56a6f31d98be9fb6fa89001cc2..707c542685db0c6e91dfb612b6cd9b45b38e90a3 100644 --- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h +++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h @@ -189,6 +189,11 @@ class AArch64FunctionInfo final : public MachineFunctionInfo { /// Temporary symbol used by PARTS to generate a runtime dependent modifier based on /// the position of function. Epilogue emission relys on this value beging set. MCSymbol *PartsSym = nullptr; // OHOS_LOCAL + +#ifdef ARK_GC_SUPPORT + SmallVector ArkArgInfos; // OHOS_LOCAL +#endif + public: explicit AArch64FunctionInfo(MachineFunction &MF); @@ -438,6 +443,16 @@ public: // OHOS_LOCAL begin void setPartsSym(MCSymbol *Sym) { PartsSym = Sym; } MCSymbol *getPartsSym() const { return PartsSym; } + +#ifdef ARK_GC_SUPPORT + void addArkArgInfo(int64_t MemOffset, Register Reg, int32_t OriginIndex) { + ArkArgInfos.emplace_back(MemOffset, Reg, OriginIndex); + } + SmallVector getArkArgInfos() const { + return ArkArgInfos; + } +#endif + // OHOS_LOCAL end private: // Hold the lists of LOHs. diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index 0267b00aefba2dc5226447c1d77cc3b6d1179c31..677a490d2046304c33eee72d608a9d10eac0748c 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -3977,4 +3977,68 @@ void X86FrameLowering::restoreWinEHStackPointersInParent( int X86FrameLowering::getOffsetOfLocalArea(CallingConv::ID CC) const { return CC == CallingConv::ArkInt ? 0 : TargetFrameLowering::getOffsetOfLocalArea(); } + +#ifdef ARK_GC_SUPPORT +namespace { +int64_t getStringAttrToInt(const Function &F, const StringRef Key) { + int64_t Value = 0; + bool Res = F.getFnAttribute(Key).getValueAsString().getAsInteger(10,Value); + assert(!Res && "Can get attribute to int"); + return Value; +} +} // namespace + +void X86FrameLowering::adjustForArkFrame(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const { + const auto &F = MF.getFunction(); + const MachineFrameInfo &MFI = MF.getFrameInfo(); + const X86MachineFunctionInfo *FuncInfo = MF.getInfo(); + assert(Uses64BitFramePtr && "only support 64Bit Frame Pointer"); + const int64_t FPSlot = hasFP(MF) ? 8 : 0; + auto InsertPos = PrologueMBB.begin(); + auto DL = InsertPos->getDebugLoc(); + if (F.hasFnAttribute(TypeKey)) { + assert(F.hasFnAttribute(TypeOffsetKey) && "missing ark-frame-type-offset"); + const int64_t ArkFrameType = getStringAttrToInt(F, TypeKey); + const int64_t FrameTypeOffset = getStringAttrToInt(F, TypeOffsetKey); + // movq $ArkFrameType, (-FPSlot - FrameTypeOffset)(%rsp) + addRegOffset(BuildMI(PrologueMBB, InsertPos, InsertPos->getDebugLoc(), + TII.get(X86::MOV64mi32)), + StackPtr, false, -FPSlot - FrameTypeOffset) + .addImm(ArkFrameType); + } + if (F.hasFnAttribute(JSFuncIdxKey)) { + assert(F.hasFnAttribute(JSFuncIdxOffsetKey) && + "missing ark-jsfunc-arg-idx-offset"); + + const int64_t JSFuncIdx = getStringAttrToInt(F, JSFuncIdxKey); + const int64_t JSFuncOffset = getStringAttrToInt(F, JSFuncIdxOffsetKey); + + using ArkArgInfo = MachineFunctionInfo::ArkArgInfo; + ArkArgInfo *JSFuncArg = + llvm::find_if(FuncInfo->getArkArgInfos(), [JSFuncIdx](ArkArgInfo Arg) { + return Arg.OriginIndex == JSFuncIdx; + }); + + Register ScratchJSFuncReg; + unsigned Flags = 0; + if (JSFuncArg->Reg != MCRegister::NoRegister) { + // ScratchJSFuncReg is the JSFuncIdx arg register. + ScratchJSFuncReg = JSFuncArg->Reg; + } else { + // mov (retaddrsize + JSFuncArg->MemOffset)(%rsp),%ScratchJSFuncReg + constexpr int Retaddrsize = 8; + ScratchJSFuncReg = GetScratchRegister(Is64Bit, IsLP64, MF, true); + addRegOffset(BuildMI(PrologueMBB, InsertPos, DL, TII.get(X86::MOV64rm), + ScratchJSFuncReg), + StackPtr, false, Retaddrsize + JSFuncArg->MemOffset); + Flags = RegState::Kill; + } + // mov %ScratchJSFuncReg,(-FPSlot - JSFuncOffset)(%rsp) + addRegOffset(BuildMI(PrologueMBB, InsertPos, DL, TII.get(X86::MOV64mr)), + StackPtr, false, -FPSlot - JSFuncOffset) + .addReg(ScratchJSFuncReg, Flags); + } +} // OHOS_LOCAL end +#endif diff --git a/llvm/lib/Target/X86/X86FrameLowering.h b/llvm/lib/Target/X86/X86FrameLowering.h index 9783c7ca2d358cce6a48864fdde196ba5a38e776..1857878ee348ee23a0d9374e608d63cd323a7799 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.h +++ b/llvm/lib/Target/X86/X86FrameLowering.h @@ -280,6 +280,12 @@ private: // OHOS_LOCAL begin int getOffsetOfLocalArea(CallingConv::ID CC = CallingConv::C) const override; + +#ifdef ARK_GC_SUPPORT + void adjustForArkFrame(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const override; +#endif + // OHOS_LOCAL end }; diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 3f8336b2590046f733ef3dbee4aa3c0f8f2343d2..527ca29e58d9861e8f64f8c812367cc78d8edfdd 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -4157,10 +4157,22 @@ SDValue X86TargetLowering::LowerFormalArguments( } else ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); } +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL + // Record the register and index of every argument which in register. + FuncInfo->addArkArgInfo(0, VA.getLocReg(), Ins[InsIndex].getOrigArgIndex()); +#endif } else { assert(VA.isMemLoc()); ArgValue = LowerMemArgument(Chain, CallConv, Ins, dl, DAG, VA, MFI, InsIndex); +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL + // Record the offset (relative to SP) and index of every argument which on + // stack. + FuncInfo->addArkArgInfo(VA.getLocMemOffset(), MCRegister::NoRegister, + Ins[InsIndex].getOrigArgIndex()); +#endif } // If value is passed via pointer - do a load. diff --git a/llvm/lib/Target/X86/X86MachineFunctionInfo.h b/llvm/lib/Target/X86/X86MachineFunctionInfo.h index 99cc9f525b2cb9e8e7b04fa0866b50def2611d26..84df3a3900475db68bc85cf83f34a151a707c754 100644 --- a/llvm/lib/Target/X86/X86MachineFunctionInfo.h +++ b/llvm/lib/Target/X86/X86MachineFunctionInfo.h @@ -125,6 +125,10 @@ class X86MachineFunctionInfo : public MachineFunctionInfo { SmallVector PreallocatedStackSizes; SmallVector, 0> PreallocatedArgOffsets; +#ifdef ARK_GC_SUPPORT + SmallVector ArkArgInfos; // OHOS_LOCAL +#endif + private: /// ForwardedMustTailRegParms - A list of virtual and physical registers /// that must be forwarded to every musttail call. @@ -253,6 +257,18 @@ public: assert(!PreallocatedArgOffsets[Id].empty() && "arg offsets not set"); return PreallocatedArgOffsets[Id]; } + +#ifdef ARK_GC_SUPPORT + // OHOS_LOCAL begin + void addArkArgInfo(int64_t MemOffset, Register Reg, int32_t OriginIndex) { + ArkArgInfos.emplace_back(MemOffset, Reg, OriginIndex); + } + SmallVector getArkArgInfos() const { + return ArkArgInfos; + } + // OHOS_LOCAL end +#endif + }; } // End llvm namespace diff --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt index e7dd22261cc4870aa0e4fae04df4b01f915fb392..dd55dd4ff8044d4abe8d7f08089a01e9ecc7e344 100644 --- a/llvm/test/CMakeLists.txt +++ b/llvm/test/CMakeLists.txt @@ -24,6 +24,7 @@ llvm_canonicalize_cmake_booleans( LLVM_ENABLE_EXPENSIVE_CHECKS LLVM_INCLUDE_DXIL_TESTS LLVM_TOOL_LLVM_DRIVER_BUILD + BUILD_ARK_GC_SUPPORT ) configure_lit_site_cfg( diff --git a/llvm/test/CodeGen/AArch64/ArkCompiler/frame-save.ll b/llvm/test/CodeGen/AArch64/ArkCompiler/frame-save.ll new file mode 100644 index 0000000000000000000000000000000000000000..792196fe7353206048f7ef7b27e965f9e67a40c0 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ArkCompiler/frame-save.ll @@ -0,0 +1,201 @@ +; RUN: llc -mtriple=aarch64-unknown-linux-gnu -O2 < %s | FileCheck %s +; ark-compiler use aarch64-unknown-linux-gnu as target currently, so use same target instead of ohos target to test it. + +; REQUIRES: ark_gc_support + +; CHECK-LABEL: SaveFrameType0: +; CHECK: sub sp, sp, #32 +; CHECK: str xzr, [sp, #8] +; CHECK: add x29, sp, #16 +define i32 @SaveFrameType0() #0 { +entry: + ret i32 0 +} +attributes #0 = { "ark-frame-type"="0" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameType1: +; CHECK: sub sp, sp, #32 +; CHECK: mov x8, #5 +; CHECK-NEXT: str x8, [sp, #8] +; CHECK: add x29, sp, #16 +define i32 @SaveFrameType1() #1 { +entry: + ret i32 0 +} +attributes #1 = { "ark-frame-type"="5" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameTypeAndJsfunc0: +; CHECK: stp x0, xzr, [sp, #-32]! +; CHECK: add x29, sp, #16 +define i32 @SaveFrameTypeAndJsfunc0(i64 %i) #2 { +entry: + ret i32 0 +} +attributes #2 = { "ark-frame-type"="0" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="0" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: SaveFrameTypeAndJsfunc1: +; CHECK: mov x8, #24 +; CHECK-NEXT: stp x0, x8, [sp, #-32]! +; CHECK: add x29, sp, #16 +define i32 @SaveFrameTypeAndJsfunc1(i64 %i) #3 { +entry: + ret i32 0 +} +attributes #3 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="0" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + + +; CHECK-LABEL: SaveFrameTypeAndJsfunc2: +; CHECK: sub sp, sp, #32 +; CHECK: mov x8, #24 +; CHECK-NEXT: ldr x9, [sp, #32] +; CHECK-NEXT: stp x9, x8, [sp] +; CHECK: add x29, sp, #16 +define webkit_jscc i32 @SaveFrameTypeAndJsfunc2(i64 %i, i64 %j) #4 { +entry: + ret i32 0 +} +attributes #4 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: SaveFrameTypeWithLargeStack: +; CHECK: sub sp, sp, #496 +; CHECK-NEXT: .cfi_def_cfa_offset 496 +; CHECK-NEXT: mov x8, #5 +; CHECK-NEXT: str x8, [sp, #456] +; CHECK: add x29, sp, #464 +define i32 @SaveFrameTypeWithLargeStack() #5 { +entry: + %buf = alloca [56 x i64], align 8 + ret i32 0 +} +attributes #5 = { "ark-frame-type"="5" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameTypeWithLargeStack1: +; CHECK: sub sp, sp, #496 +; CHECK-NEXT: .cfi_def_cfa_offset 496 +; CHECK-NEXT: mov x8, #5 +; CHECK-NEXT: str x8, [sp, #456] +; CHECK: add x29, sp, #464 +define i32 @SaveFrameTypeWithLargeStack1() #6 { +entry: + %buf = alloca [57 x i64], align 8 + ret i32 0 +} +attributes #6 = { "ark-frame-type"="5" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameTypeWithLargeStack2: +; CHECK: stp x29, x30, [sp, #-32]! +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: mov x8, #5 +; CHECK-NEXT: str x8, [sp, #8] +; CHECK-NEXT: add x29, sp, #16 +; CHECK: sub sp, sp, #464 +define i32 @SaveFrameTypeWithLargeStack2() #7 { +entry: + %buf = alloca [58 x i64], align 8 + ret i32 0 +} +attributes #7 = { "ark-frame-type"="5" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameTypeWithHugeStack: +; CHECK: stp x29, x30, [sp, #-32]! +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: mov x8, #5 +; CHECK-NEXT: str x8, [sp, #8] +; CHECK-NEXT: add x29, sp, #16 +; CHECK: sub sp, sp, #127, lsl #12 +; CHECK-NEXT: sub sp, sp, #4080 + +define i32 @SaveFrameTypeWithHugeStack() #7 { +entry: + %buf = alloca [65535 x i64], align 8 + ret i32 0 +} +attributes #7 = { "ark-frame-type"="5" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: SaveFrameTypeAndJsfuncWithLargeStack: +; CHECK: sub sp, sp, #496 +; CHECK-NEXT: .cfi_def_cfa_offset 496 +; CHECK-NEXT: mov x8, #24 +; CHECK-NEXT: ldr x9, [sp, #496] +; CHECK-NEXT: stp x9, x8, [sp, #448] +; CHECK: add x29, sp, #464 +define webkit_jscc i32 @SaveFrameTypeAndJsfuncWithLargeStack(i64 %i, i64 %j) #8 { +entry: + %buf = alloca [56 x i64], align 8 + ret i32 0 +} +attributes #8 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + + +; CHECK-LABEL: SaveFrameTypeAndJsfuncWithLargeStack1: +; CHECK: stp x29, x30, [sp, #-32]! +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: mov x8, #24 +; CHECK-NEXT: ldr x9, [sp, #48] +; CHECK-NEXT: stp x9, x8, [sp] +; CHECK-NEXT: add x29, sp, #16 +; CHECK: sub sp, sp, #464 + +define webkit_jscc i32 @SaveFrameTypeAndJsfuncWithLargeStack1(i64 %i, i64 %j) #9 { +entry: + %buf = alloca [57 x i64], align 8 + ret i32 0 +} +attributes #9 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: SaveFrameTypeAndJsfuncWithLargeStack2: +; CHECK: stp x29, x30, [sp, #-32]! +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK: mov x8, #24 +; CHECK: stp x1, x8, [sp, #-16]! +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: add x29, sp, #16 +; CHECK: sub sp, sp, #464 + +define i32 @SaveFrameTypeAndJsfuncWithLargeStack2(i64 %i, i64 %j) #10 { +entry: + %buf = alloca [57 x i64], align 8 + ret i32 0 +} +attributes #10 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: SaveFrameTypeAndJsfuncWithLargeStack3: +; CHECK: sub sp, sp, #496 +; CHECK-NEXT: .cfi_def_cfa_offset 496 +; CHECK-NEXT: mov x8, #24 +; CHECK-NEXT: ldr x9, [sp, #496] +; CHECK-NEXT: stp x9, x8, [sp, #384] +; CHECK: add x29, sp, #400 + +define webkit_jscc i32 @SaveFrameTypeAndJsfuncWithLargeStack3(i64 %i, i64 %j) #11 { +entry: + %buf = alloca [47 x i64], align 8 + call void asm sideeffect "nop", "~{x0},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x13},~{x14},~{x15},~{x16},~{x17},~{x18},~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28},~{memory}"() nounwind + ret i32 0 +} +attributes #11 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: SaveFrameTypeAndJsfuncWithLargeStack4: +; CHECK: stp x29, x30, [sp, #-96]! +; CHECK-NEXT: .cfi_def_cfa_offset 96 +; CHECK: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 112 +; CHECK-NEXT: mov x8, #24 +; CHECK-NEXT: ldr x9, [sp, #112] +; CHECK-NEXT: stp x9, x8, [sp] +; CHECK-NEXT: add x29, sp, #16 +; CHECK: sub sp, sp, #400 + +define webkit_jscc i32 @SaveFrameTypeAndJsfuncWithLargeStack4(i64 %i, i64 %j) #12 { +entry: + %buf = alloca [48 x i64], align 8 + call void asm sideeffect "nop", "~{x0},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x13},~{x14},~{x15},~{x16},~{x17},~{x18},~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28},~{memory}"() nounwind + ret i32 0 +} +attributes #12 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } diff --git a/llvm/test/CodeGen/X86/ArkCompiler/frame-save.ll b/llvm/test/CodeGen/X86/ArkCompiler/frame-save.ll new file mode 100644 index 0000000000000000000000000000000000000000..2d4bb27e22fdf1f8eb2a753f84e30c7942320ce4 --- /dev/null +++ b/llvm/test/CodeGen/X86/ArkCompiler/frame-save.ll @@ -0,0 +1,40 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O2 < %s | FileCheck %s +; ark-compiler use x86_64-unknown-linux-gnu as target currently, so use same target instead of ohos target to test it. + +; REQUIRES: ark_gc_support + +; CHECK-LABEL: saveframetype0: +; CHECK: movq $0, -16(%rsp) +; CHECK-NEXT: pushq %rbp +; CHECK: movq %rsp, %rbp +; CHECK: subq $16, %rsp +define i32 @saveframetype0() #0 { +entry: + ret i32 0 +} +attributes #0 = { "ark-frame-type"="0" "ark-frame-type-offset"="8" "frame-pointer"="all" "frame-reserved-slots"="8" } + +; CHECK-LABEL: saveframetypeAndJsfunc0: +; CHECK: movq $0, -16(%rsp) +; CHECK: movq %rdi, -24(%rsp) +; CHECK-NEXT: pushq %rbp +; CHECK: movq %rsp, %rbp +; CHECK: subq $16, %rsp +define i32 @saveframetypeAndJsfunc0(i64 %i) #2 { +entry: + ret i32 0 +} +attributes #2 = { "ark-frame-type"="0" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="0" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } + +; CHECK-LABEL: saveframetypeAndJsfunc2: +; CHECK: movq $24, -16(%rsp) +; CHECK-NEXT: movq 8(%rsp), %r11 +; CHECK-NEXT: movq %r11, -24(%rsp) +; CHECK-NEXT: pushq %rbp +; CHECK: movq %rsp, %rbp +; CHECK: subq $16, %rsp +define webkit_jscc i32 @saveframetypeAndJsfunc2(i64 %i, i64 %j) #4 { +entry: + ret i32 0 +} +attributes #4 = { "ark-frame-type"="24" "ark-frame-type-offset"="8" "ark-jsfunc-arg-idx"="1" "ark-jsfunc-arg-idx-offset"="16" "frame-pointer"="all" "frame-reserved-slots"="16" } \ No newline at end of file diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py index 75a38b4c5dad587047471a9756bab941f0c80344..bbd0c983bc9edd9b73a0d4106486ab4dc1f96f05 100644 --- a/llvm/test/lit.cfg.py +++ b/llvm/test/lit.cfg.py @@ -354,6 +354,9 @@ if config.target_triple: if config.have_llvm_driver: config.available_features.add('llvm-driver') +if config.ark_gc_support: + config.available_features.add('ark_gc_support') + import subprocess diff --git a/llvm/test/lit.site.cfg.py.in b/llvm/test/lit.site.cfg.py.in index 09210e2e56d4c7a51ef57cd0e4c8c125320f8ef7..0192624cd230dc1c08ac7cbba43f4fd5d4000029 100644 --- a/llvm/test/lit.site.cfg.py.in +++ b/llvm/test/lit.site.cfg.py.in @@ -62,6 +62,7 @@ config.llvm_raevict_model_autogenerated = @LLVM_RAEVICT_MODEL_AUTOGENERATED@ config.expensive_checks = @LLVM_ENABLE_EXPENSIVE_CHECKS@ config.dxil_tests = @LLVM_INCLUDE_DXIL_TESTS@ config.have_llvm_driver = @LLVM_TOOL_LLVM_DRIVER_BUILD@ +config.ark_gc_support = "@BUILD_ARK_GC_SUPPORT@" import lit.llvm lit.llvm.initialize(lit_config, config)