diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 0e85afa82c7..43756892e40 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -505,8 +505,15 @@ option(LLVM_BUILD_RUNTIME "Build the LLVM runtime libraries." ON) option(LLVM_BUILD_EXAMPLES "Build the LLVM example programs. If OFF, just generate build targets." OFF) +option(BUILD_ARK_GC_SUPPORT + "ARK support GC. If ON, support GC." OFF) +if(BUILD_ARK_GC_SUPPORT) + add_definitions(-DARK_GC_SUPPORT) +endif(BUILD_ARK_GC_SUPPORT) + option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) + if(LLVM_BUILD_EXAMPLES) add_definitions(-DBUILD_EXAMPLES) endif(LLVM_BUILD_EXAMPLES) diff --git a/llvm/include/llvm-c/ExecutionEngine.h b/llvm/include/llvm-c/ExecutionEngine.h index f31b97ad762..ceda6a19496 100644 --- a/llvm/include/llvm-c/ExecutionEngine.h +++ b/llvm/include/llvm-c/ExecutionEngine.h @@ -42,6 +42,7 @@ typedef struct LLVMOpaqueMCJITMemoryManager *LLVMMCJITMemoryManagerRef; struct LLVMMCJITCompilerOptions { unsigned OptLevel; + LLVMRelocMode RelMode; LLVMCodeModel CodeModel; LLVMBool NoFramePointerElim; LLVMBool EnableFastISel; diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h index c7d4c4d7e5d..1df40696dd0 100644 --- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -15,6 +15,9 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/ADT/StringSwitch.h" +#ifdef ARK_GC_SUPPORT +#include "llvm/ADT/Triple.h" +#endif #include #include @@ -177,7 +180,12 @@ public: MachineBasicBlock &MBB) const = 0; virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const = 0; - +#ifdef ARK_GC_SUPPORT + virtual Triple::ArchType GetArkSupportTarget() const + { + return Triple::UnknownArch; + } +#endif /// Replace a StackProbe stub (if any) with the actual probe code inline virtual void inlineStackProbe(MachineFunction &MF, MachineBasicBlock &PrologueMBB) const {} diff --git a/llvm/include/llvm/Target/CodeGenCWrappers.h b/llvm/include/llvm/Target/CodeGenCWrappers.h index a9954635705..a0a533a7153 100644 --- a/llvm/include/llvm/Target/CodeGenCWrappers.h +++ b/llvm/include/llvm/Target/CodeGenCWrappers.h @@ -59,6 +59,36 @@ inline LLVMCodeModel wrap(CodeModel::Model Model) { } llvm_unreachable("Bad CodeModel!"); } + +inline Reloc::Model unwrap(LLVMRelocMode Model) { + switch (Model) { + case LLVMRelocDefault: + case LLVMRelocStatic: + return Reloc::Static; + case LLVMRelocPIC: + return Reloc::PIC_; + case LLVMRelocDynamicNoPic: + return Reloc::DynamicNoPIC; + } + llvm_unreachable("Invalid LLVMRelocMode!"); +} + +inline LLVMRelocMode unwrap(Reloc::Model Model) { + switch (Model) { + case Reloc::Static: + return LLVMRelocStatic; + case Reloc::PIC_: + return LLVMRelocPIC; + case Reloc::DynamicNoPIC: + return LLVMRelocDynamicNoPic; + case Reloc::ROPI: + case Reloc::RWPI: + case Reloc::ROPI_RWPI: + break; + } + llvm_unreachable("Invalid Reloc::Model!"); +} + } // namespace llvm #endif diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index 3909b571728..d275d9890cf 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -79,6 +79,9 @@ using MBBVector = SmallVector; STATISTIC(NumLeafFuncWithSpills, "Number of leaf functions with CSRs"); STATISTIC(NumFuncSeen, "Number of functions seen in PEI"); +#define JS_ENTRY_FRAME_MARK 1 +#define JS_FRAME_MARK 0 + namespace { @@ -878,6 +881,32 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { int64_t FixedCSEnd = Offset; unsigned MaxAlign = MFI.getMaxAlignment(); + #ifdef ARK_GC_SUPPORT + unsigned CalleeSavedFrameSize = 0; + Triple::ArchType archType = TFI.GetArkSupportTarget(); + if (archType != Triple::UnknownArch) { + int slotSize = sizeof(uint32_t); + if (archType == Triple::aarch64) { + slotSize = sizeof(uint64_t); + } + if (MF.getFunction().hasFnAttribute("js-stub-call")) { + int64_t marker = 0x0; + MF.getFunction() + .getFnAttribute("js-stub-call") + .getValueAsString() + .getAsInteger(10, marker);//marker 1 break frame + if (marker == JS_ENTRY_FRAME_MARK) { + CalleeSavedFrameSize = 3 * slotSize; // 3 * slotSize;/* frameType + currentSP + threadSP*/ + } else if (marker == JS_FRAME_MARK){ + CalleeSavedFrameSize = 2 * slotSize; /* 2: frameType + currentSP */ + } else { + assert("js-stub-call is illeagl ! "); + } + Offset += CalleeSavedFrameSize; + } + } + #endif + // Make sure the special register scavenging spill slot is closest to the // incoming stack pointer if a frame pointer is required and is closer // to the incoming rather than the final stack pointer. diff --git a/llvm/lib/CodeGen/StackMaps.cpp b/llvm/lib/CodeGen/StackMaps.cpp index e16587c44a5..bd3e99c6600 100644 --- a/llvm/lib/CodeGen/StackMaps.cpp +++ b/llvm/lib/CodeGen/StackMaps.cpp @@ -29,6 +29,9 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#ifdef ARK_GC_SUPPORT +#include "llvm/Target/TargetMachine.h" +#endif #include #include #include @@ -442,7 +445,11 @@ void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) { LLVM_DEBUG(dbgs() << WSMP << "function addr: " << FR.first << " frame size: " << FR.second.StackSize << " callsite count: " << FR.second.RecordCount << '\n'); +#ifdef ARK_GC_SUPPORT + OS.EmitSymbolValue(FR.first, AP.TM.getProgramPointerSize()); +#else OS.EmitSymbolValue(FR.first, 8); +#endif OS.EmitIntValue(FR.second.StackSize, 8); OS.EmitIntValue(FR.second.RecordCount, 8); } diff --git a/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp index ff1e8050c7e..a18df38ab53 100644 --- a/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -198,6 +198,7 @@ LLVMBool LLVMCreateMCJITCompilerForModule( builder.setEngineKind(EngineKind::JIT) .setErrorStr(&Error) .setOptLevel((CodeGenOpt::Level)options.OptLevel) + .setRelocationModel(unwrap(options.RelMode)) .setTargetOptions(targetOptions); bool JIT; if (Optional CM = unwrap(options.CodeModel, JIT)) diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index 6da089d1859..271b4e157d9 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -95,6 +95,10 @@ public: const MachineInstr &MI); void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, const MachineInstr &MI); +#ifdef ARK_GC_SUPPORT + void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, + const MachineInstr &MI); +#endif void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI); void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI); @@ -936,6 +940,49 @@ void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0)); } +#ifdef ARK_GC_SUPPORT +void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, + const MachineInstr &MI) { + StatepointOpers SOpers(&MI); + if (unsigned PatchBytes = SOpers.getNumPatchBytes()) { + assert(PatchBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); + for (unsigned i = 0; i < PatchBytes; i += 4) + EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0)); + } else { + // Lower call target and choose correct opcode + const MachineOperand &CallTarget = SOpers.getCallTarget(); + MCOperand CallTargetMCOp; + unsigned CallOpcode; + switch (CallTarget.getType()) { + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: + MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp); + CallOpcode = AArch64::BL; + break; + case MachineOperand::MO_Immediate: + CallTargetMCOp = MCOperand::createImm(CallTarget.getImm()); + CallOpcode = AArch64::BL; + break; + case MachineOperand::MO_Register: + CallTargetMCOp = MCOperand::createReg(CallTarget.getReg()); + CallOpcode = AArch64::BLR; + break; + default: + llvm_unreachable("Unsupported operand type in statepoint call target"); + break; + } + + EmitToStreamer(OutStreamer, + MCInstBuilder(CallOpcode).addOperand(CallTargetMCOp)); + } + + auto &Ctx = OutStreamer.getContext(); + MCSymbol *MILabel = Ctx.createTempSymbol(); + OutStreamer.EmitLabel(MILabel); + SM.recordStatepoint(*MILabel, MI); +} +#endif + void AArch64AsmPrinter::EmitFMov0(const MachineInstr &MI) { Register DestReg = MI.getOperand(0).getReg(); if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround()) { @@ -1198,6 +1245,11 @@ void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) { case TargetOpcode::PATCHPOINT: return LowerPATCHPOINT(*OutStreamer, SM, *MI); +#ifdef ARK_GC_SUPPORT + case TargetOpcode::STATEPOINT: + return LowerSTATEPOINT(*OutStreamer, SM, *MI); +#endif + case TargetOpcode::PATCHABLE_FUNCTION_ENTER: LowerPATCHABLE_FUNCTION_ENTER(*MI); return; diff --git a/llvm/lib/Target/AArch64/AArch64CallingConvention.td b/llvm/lib/Target/AArch64/AArch64CallingConvention.td index a0b2d7712b6..59092f1e196 100644 --- a/llvm/lib/Target/AArch64/AArch64CallingConvention.td +++ b/llvm/lib/Target/AArch64/AArch64CallingConvention.td @@ -373,9 +373,10 @@ def CC_AArch64_GHC : CallingConv<[ // vreg on entry, use it in RET & tail call generation; make that vreg def if we // end up saving LR as part of a call frame). Watch this space... def CSR_AArch64_AAPCS : CalleeSavedRegs<(add X19, X20, X21, X22, X23, X24, - X25, X26, X27, X28, LR, FP, + X25, X26, X27, X28, D8, D9, D10, D11, - D12, D13, D14, D15)>; + D12, D13, D14, D15, + LR, FP)>; // Darwin puts the frame-record at the top of the callee-save area. def CSR_Darwin_AArch64_AAPCS : CalleeSavedRegs<(add LR, FP, X19, X20, X21, X22, diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 651ad9ad4c8..5e179bd3db8 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -385,6 +385,7 @@ void AArch64FrameLowering::emitCalleeSavedFrameMoves( unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); unsigned CFIIndex = MF.addFrameInst( MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset)); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex) .setMIFlags(MachineInstr::FrameSetup); @@ -535,10 +536,11 @@ static MachineBasicBlock::iterator InsertSEH(MachineBasicBlock::iterator MBBI, case AArch64::STPXpre: { Register Reg0 = MBBI->getOperand(1).getReg(); Register Reg1 = MBBI->getOperand(2).getReg(); - if (Reg0 == AArch64::FP && Reg1 == AArch64::LR) + if (Reg0 == AArch64::FP && Reg1 == AArch64::LR) { MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveFPLR_X)) .addImm(Imm * 8) .setMIFlag(Flag); + } else MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveRegP_X)) .addImm(RegInfo->getSEHRegNum(Reg0)) @@ -584,10 +586,11 @@ static MachineBasicBlock::iterator InsertSEH(MachineBasicBlock::iterator MBBI, case AArch64::LDPXi: { Register Reg0 = MBBI->getOperand(0).getReg(); Register Reg1 = MBBI->getOperand(1).getReg(); - if (Reg0 == AArch64::FP && Reg1 == AArch64::LR) + if (Reg0 == AArch64::FP && Reg1 == AArch64::LR) { MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveFPLR)) .addImm(Imm * 8) .setMIFlag(Flag); + } else MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveRegP)) .addImm(RegInfo->getSEHRegNum(Reg0)) @@ -872,6 +875,13 @@ static bool IsSVECalleeSave(MachineBasicBlock::iterator I) { } } +#ifdef ARK_GC_SUPPORT +Triple::ArchType AArch64FrameLowering::GetArkSupportTarget() const +{ + return Triple::aarch64; +} +#endif + void AArch64FrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.begin(); @@ -980,6 +990,7 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, unsigned FixedObject = getFixedObjectSize(MF, AFI, IsWin64, IsFunclet); auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject; + // All of the remaining stack allocations are for locals. AFI->setLocalStackSize(NumBytes - PrologueSaveSize); bool CombineSPBump = shouldCombineCSRLocalStackBump(MF, NumBytes); @@ -1020,11 +1031,13 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, // mov fp,sp when FPOffset is zero. // Note: All stores of callee-saved registers are marked as "FrameSetup". // This code marks the instruction(s) that set the FP also. + emitFrameOffset(MBB, MBBI, DL, AArch64::FP, AArch64::SP, {FPOffset, MVT::i8}, TII, MachineInstr::FrameSetup, false, NeedsWinCFI, &HasWinCFI); } + if (windowsRequiresStackProbe(MF, NumBytes)) { uint64_t NumWords = NumBytes >> 4; if (NeedsWinCFI) { @@ -1514,6 +1527,8 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, const StackOffset &SVEStackSize = getSVEStackSize(MF); + + // If there is a single SP update, insert it before the ret and we're done. if (CombineSPBump) { assert(!SVEStackSize && "Cannot combine SP bump with SVE"); @@ -1552,6 +1567,8 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, DeallocateAfter = SVEStackSize - DeallocateBefore; } + + // Deallocate the SVE area. if (SVEStackSize) { if (AFI->isStackRealigned()) { @@ -1632,6 +1649,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, // This must be placed after the callee-save restore code because that code // assumes the SP is at the same location as it was after the callee-save save // code in the prologue. + if (AfterCSRPopSize) { // Find an insertion point for the first ldp so that it goes before the // shadow call stack epilog instruction. This ensures that the restore of @@ -2079,6 +2097,7 @@ static void computeCalleeSaveRegisterPairs( RegPairs.push_back(RPI); if (RPI.isPaired()) ++i; + } } @@ -2234,6 +2253,8 @@ bool AArch64FrameLowering::restoreCalleeSavedRegisters( SmallVector RegPairs; bool NeedsWinCFI = needsWinCFI(MF); + + if (MI != MBB.end()) DL = MI->getDebugLoc(); @@ -2416,6 +2437,7 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF, CSStackSize += RegSize; } + // Save number of saved regs, so we can easily update CSStackSize later. unsigned NumSavedRegs = SavedRegs.count(); diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.h b/llvm/lib/Target/AArch64/AArch64FrameLowering.h index b5719feb6b1..b09aa05176d 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.h +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.h @@ -15,6 +15,11 @@ #include "AArch64StackOffset.h" #include "llvm/CodeGen/TargetFrameLowering.h" +#ifdef ARK_GC_SUPPORT +#include "llvm/ADT/Triple.h" +#endif + +#define JS_ENTRY_FRAME_MARK 1 namespace llvm { @@ -35,6 +40,9 @@ public: /// the function. void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; +#ifdef ARK_GC_SUPPORT + Triple::ArchType GetArkSupportTarget() const override; +#endif bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 23f05eaad94..974d11aa701 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -1498,6 +1498,10 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter( case TargetOpcode::STACKMAP: case TargetOpcode::PATCHPOINT: +#ifdef ARK_GC_SUPPORT + case TargetOpcode::STATEPOINT: + MI.addOperand(*BB->getParent(), MachineOperand::CreateReg(AArch64::LR, true, true)); +#endif return emitPatchPoint(MI, BB); case AArch64::CATCHRET: diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 54f3f7c1013..c57374c9c78 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -107,6 +107,15 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { NumBytes = PatchPointOpers(&MI).getNumPatchBytes(); assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); break; +#ifdef ARK_GC_SUPPORT + case TargetOpcode::STATEPOINT: + NumBytes = StatepointOpers(&MI).getNumPatchBytes(); + assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); + // No patch bytes means a normal call inst is emitted + if (NumBytes == 0) + NumBytes = 4; + break; +#endif case AArch64::TLSDESC_CALLSEQ: // This gets lowered to an instruction sequence which takes 16 bytes NumBytes = 16; diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index 14f839cd4f8..f305d3abdbf 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -464,8 +464,14 @@ void AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, unsigned FrameReg; // Special handling of dbg_value, stackmap and patchpoint instructions. +#ifdef ARK_GC_SUPPORT + if (MI.isDebugValue() || MI.getOpcode() == TargetOpcode::STACKMAP || + MI.getOpcode() == TargetOpcode::PATCHPOINT || + MI.getOpcode() == TargetOpcode::STATEPOINT) { +#else if (MI.isDebugValue() || MI.getOpcode() == TargetOpcode::STACKMAP || MI.getOpcode() == TargetOpcode::PATCHPOINT) { +#endif StackOffset Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, /*PreferFP=*/true, diff --git a/llvm/lib/Target/AArch64/AArch64StackOffset.h b/llvm/lib/Target/AArch64/AArch64StackOffset.h index f95b5dc5246..99f5905565a 100644 --- a/llvm/lib/Target/AArch64/AArch64StackOffset.h +++ b/llvm/lib/Target/AArch64/AArch64StackOffset.h @@ -37,7 +37,7 @@ namespace llvm { class StackOffset { int64_t Bytes; int64_t ScalableBytes; - +public: explicit operator int() const; public: diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp index 4724d6b8dae..2155ad923f9 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -189,6 +189,12 @@ int AArch64TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) return TTI::TCC_Free; break; +#ifdef ARK_GC_SUPPORT + case Intrinsic::experimental_gc_statepoint: + if ((Idx < 5) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) + return TTI::TCC_Free; + break; +#endif } return AArch64TTIImpl::getIntImmCost(Imm, Ty); } diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index 6f26ca127f9..20b2a76518f 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -55,7 +55,11 @@ using namespace llvm; ARMAsmPrinter::ARMAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) : AsmPrinter(TM, std::move(Streamer)), Subtarget(nullptr), AFI(nullptr), +#ifdef ARK_GC_SUPPORT + MCP(nullptr), InConstantPool(false), OptimizationGoals(-1), SM(*this) {} +#else MCP(nullptr), InConstantPool(false), OptimizationGoals(-1) {} +#endif void ARMAsmPrinter::EmitFunctionBodyEnd() { // Make sure to terminate any constant pools that were at the end @@ -567,6 +571,10 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { OptimizationGoals = -1; ATS.finishAttributeSection(); + +#ifdef ARK_GC_SUPPORT + SM.serializeToStackMapSection(); +#endif } //===----------------------------------------------------------------------===// @@ -2135,6 +2143,14 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { case ARM::PATCHABLE_TAIL_CALL: LowerPATCHABLE_TAIL_CALL(*MI); return; +#ifdef ARK_GC_SUPPORT + case TargetOpcode::STACKMAP: + return LowerSTACKMAP(*OutStreamer, SM, *MI); + case TargetOpcode::PATCHPOINT: + return LowerPATCHPOINT(*OutStreamer, SM, *MI); + case TargetOpcode::STATEPOINT: + return LowerSTATEPOINT(*OutStreamer, SM, *MI); +#endif } MCInst TmpInst; @@ -2143,6 +2159,76 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, TmpInst); } +#ifdef ARK_GC_SUPPORT +static unsigned roundUpTo4ByteAligned(unsigned n) { + unsigned mask = 3; + unsigned rev = ~3; + n = (n & rev) + (((n & mask) + mask) & rev); + return n; +} + +void ARMAsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM, + const MachineInstr &MI) { + llvm_unreachable("Stackmap lowering is not implemented"); +} + +void ARMAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, + const MachineInstr &MI) { + llvm_unreachable("Patchpoint lowering is not implemented"); +} + +void ARMAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, + const MachineInstr &MI) { + assert(!AFI->isThumbFunction()); + + StatepointOpers SOpers(&MI); + MCInst Noop; + Subtarget->getInstrInfo()->getNoop(Noop); + if (unsigned PatchBytes = SOpers.getNumPatchBytes()) { + unsigned NumBytes = roundUpTo4ByteAligned(PatchBytes); + unsigned EncodedBytes = 0; + assert(NumBytes >= EncodedBytes && + "Statepoint can't request size less than the length of a call."); + assert((NumBytes - EncodedBytes) % 4 == 0 && + "Invalid number of NOP bytes requested!"); + MCInst Noop; + Subtarget->getInstrInfo()->getNoop(Noop); + for (unsigned i = EncodedBytes; i < NumBytes; i += 4) + EmitToStreamer(OutStreamer, Noop); + } else { + const MachineOperand &CallTarget = SOpers.getCallTarget(); + MCOperand CallTargetMCOp; + unsigned CallOpcode; + switch (CallTarget.getType()) { + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: + ARMAsmPrinter::lowerOperand(CallTarget, CallTargetMCOp); + CallOpcode = ARM::BL; + break; + case MachineOperand::MO_Immediate: + CallTargetMCOp = MCOperand::createImm(CallTarget.getImm()); + CallOpcode = ARM::BL; + break; + case MachineOperand::MO_Register: + CallTargetMCOp = MCOperand::createReg(CallTarget.getReg()); + CallOpcode = ARM::BLX; + break; + default: + llvm_unreachable("Unsupported operand type in statepoint call target"); + break; + } + + EmitToStreamer(OutStreamer, + MCInstBuilder(CallOpcode).addOperand(CallTargetMCOp)); + } + + auto &Ctx = OutStreamer.getContext(); + MCSymbol *MILabel = Ctx.createTempSymbol(); + OutStreamer.EmitLabel(MILabel); + SM.recordStatepoint(*MILabel, MI); +} +#endif + //===----------------------------------------------------------------------===// // Target Registry Stuff //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.h b/llvm/lib/Target/ARM/ARMAsmPrinter.h index a4b37fa2331..be62b1875f4 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.h +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.h @@ -11,6 +11,9 @@ #include "ARMSubtarget.h" #include "llvm/CodeGen/AsmPrinter.h" +#ifdef ARK_GC_SUPPORT +#include "llvm/CodeGen/StackMaps.h" +#endif #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -65,6 +68,10 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter { /// debug info can link properly. SmallPtrSet EmittedPromotedGlobalLabels; +#ifdef ARK_GC_SUPPORT + StackMaps SM; +#endif + public: explicit ARMAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer); @@ -129,6 +136,17 @@ private: bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, const MachineInstr *MI); +#ifdef ARK_GC_SUPPORT + void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM, + const MachineInstr &MI); + + void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, + const MachineInstr &MI); + + void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, + const MachineInstr &MI); +#endif + public: unsigned getISAEncoding() override { // ARM/Darwin adds ISA to the DWARF info for each function. diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp index 48f78151025..0970a6259ad 100644 --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -712,6 +712,11 @@ unsigned ARMBaseInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { return 0; case TargetOpcode::BUNDLE: return getInstBundleLength(MI); +#ifdef ARK_GC_SUPPORT + case TargetOpcode::PATCHPOINT: + case TargetOpcode::STATEPOINT: + return MI.getOperand(1).getImm(); +#endif case ARM::MOVi16_ga_pcrel: case ARM::MOVTi16_ga_pcrel: case ARM::t2MOVi16_ga_pcrel: diff --git a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp index 66ad120a111..59335c77394 100644 --- a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -831,6 +831,11 @@ initializeFunctionInfo(const std::vector &CPEMIs) { NegOk = true; break; } + // Decrease a bit here to workaround the out of range pc-relative + // fixup value error during the MCJIT compilation process + if (Bits > 0) { + Bits--; + } // Remember that this is a user of a CP entry. unsigned CPI = I.getOperand(op).getIndex(); diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp index cb98b2b34ef..1806214932e 100644 --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -1573,6 +1573,7 @@ static unsigned estimateRSStackSizeLimit(MachineFunction &MF, Limit = std::min(Limit, ((1U << 7) - 1) * 4); break; default: + break; llvm_unreachable("Unhandled addressing mode in stack size limit calculation"); } break; // At most one FI per instruction diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 9f504b1eaa4..30a1baf5c85 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -10551,6 +10551,14 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, llvm_unreachable("Unexpected instr type to insert"); } +#ifdef ARK_GC_SUPPORT + case TargetOpcode::STATEPOINT: + case TargetOpcode::STACKMAP: + case TargetOpcode::PATCHPOINT: + MI.addOperand(*BB->getParent(), MachineOperand::CreateReg(ARM::LR, true, true)); + return emitPatchPoint(MI, BB); +#endif + // Thumb1 post-indexed loads are really just single-register LDMs. case ARM::tLDR_postidx: { MachineOperand Def(MI.getOperand(1)); diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index 1da20371caf..42b557f97a0 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -1168,6 +1168,30 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, else MFI.setOffsetAdjustment(-StackSize); } +#ifdef ARK_GC_SUPPORT + // push marker + if (MF.getFunction().hasFnAttribute("js-stub-call")) + { + int64_t marker = 0x0; + MF.getFunction() + .getFnAttribute("js-stub-call") + .getValueAsString() + .getAsInteger(10, marker);//marker 1 break frame + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) + .addImm(marker) + .setMIFlag(MachineInstr::FrameSetup); // type + + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) + .addImm(marker) + .setMIFlag(MachineInstr::FrameSetup); // current sp + + if (marker == JS_ENTRY_FRAME_MARK) { + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) + .addImm(marker) + .setMIFlag(MachineInstr::FrameSetup); // thread sp + } + } +#endif // For EH funclets, only allocate enough space for outgoing calls. Save the // NumBytes value that we would've used for the parent frame. @@ -1635,6 +1659,31 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, uint64_t SEHStackAllocAmt = NumBytes; if (HasFP) { +#ifdef ARK_GC_SUPPORT + if (MF.getFunction().hasFnAttribute("js-stub-call")) + { + int64_t marker = 0x0; + MF.getFunction() + .getFnAttribute("js-stub-call") + .getValueAsString() + .getAsInteger(10, marker);//marker 1 break frame + + // pop marker + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) + .setMIFlag(MachineInstr::FrameDestroy); + // pop currentSP + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) + .setMIFlag(MachineInstr::FrameDestroy); + if (marker == JS_ENTRY_FRAME_MARK) { + // pop thread.fp + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) + .setMIFlag(MachineInstr::FrameDestroy); + } + } +#endif // Pop EBP. BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), MachineFramePtr) @@ -1993,8 +2042,31 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( if (hasFP(MF)) { // emitPrologue always spills frame register the first thing. +#ifdef ARK_GC_SUPPORT + if (MF.getFunction().hasFnAttribute("js-stub-call")) { + int64_t marker = 0x0; + MF.getFunction() + .getFnAttribute("js-stub-call") + .getValueAsString() + .getAsInteger(10, marker);//marker 1 break frame + + if (marker == JS_ENTRY_FRAME_MARK) { + SpillSlotOffset -= 4 * SlotSize; // add type and thread.fp and currentsp and threadfp + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + CalleeSavedFrameSize += (3 * SlotSize); + } else { + SpillSlotOffset -= 3 * SlotSize; // add type and pre and currentsp + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); // prev + CalleeSavedFrameSize += 2 * SlotSize; + } + } else { + SpillSlotOffset -= SlotSize; // add type and thread.fp + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + } +#else SpillSlotOffset -= SlotSize; MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); +#endif // Since emitPrologue and emitEpilogue will handle spilling and restoring of // the frame register, we can delete it from CSI list and not have to worry diff --git a/llvm/lib/Target/X86/X86FrameLowering.h b/llvm/lib/Target/X86/X86FrameLowering.h index 2103d6471ea..3fd89b0d9ee 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.h +++ b/llvm/lib/Target/X86/X86FrameLowering.h @@ -15,6 +15,8 @@ #include "llvm/CodeGen/TargetFrameLowering.h" +#define JS_ENTRY_FRAME_MARK 1 + namespace llvm { class MachineInstrBuilder;