Index: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp =================================================================== --- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp +++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp @@ -21,6 +21,7 @@ CommentString = "#"; AlignmentIsInBytes = false; SupportsDebugInformation = true; + ExceptionsType = ExceptionHandling::DwarfCFI; Data16bitsDirective = "\t.half\t"; Data32bitsDirective = "\t.word\t"; } Index: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp =================================================================== --- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp +++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -50,7 +50,13 @@ static MCAsmInfo *createRISCVMCAsmInfo(const MCRegisterInfo &MRI, const Triple &TT) { - return new RISCVMCAsmInfo(TT); + MCAsmInfo *MAI = new RISCVMCAsmInfo(TT); + + unsigned SP = MRI.getDwarfRegNum(RISCV::X2, true); + MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, SP, 0); + MAI->addInitialFrameState(Inst); + + return MAI; } static MCSubtargetInfo *createRISCVMCSubtargetInfo(const Triple &TT, Index: llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.cpp =================================================================== --- llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.cpp +++ llvm/trunk/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -18,6 +18,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/MC/MCDwarf.h" using namespace llvm; @@ -96,6 +97,8 @@ MachineFrameInfo &MFI = MF.getFrameInfo(); auto *RVFI = MF.getInfo(); + const RISCVRegisterInfo *RI = STI.getRegisterInfo(); + const RISCVInstrInfo *TII = STI.getInstrInfo(); MachineBasicBlock::iterator MBBI = MBB.begin(); unsigned FPReg = getFPReg(STI); @@ -119,6 +122,12 @@ // Allocate space on the stack if necessary. adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup); + // Emit ".cfi_def_cfa_offset StackSize" + unsigned CFIIndex = MF.addFrameInst( + MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize)); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); + // The frame pointer is callee-saved, and code has been generated for us to // save it to the stack. We need to skip over the storing of callee-saved // registers as the frame pointer must be modified after it has been saved @@ -128,10 +137,28 @@ const std::vector &CSI = MFI.getCalleeSavedInfo(); std::advance(MBBI, CSI.size()); + // Iterate over list of callee-saved registers and emit .cfi_offset + // directives. + for (const auto &Entry : CSI) { + int64_t Offset = MFI.getObjectOffset(Entry.getFrameIdx()); + unsigned Reg = Entry.getReg(); + unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( + nullptr, RI->getDwarfRegNum(Reg, true), Offset)); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); + } + // Generate new FP. - if (hasFP(MF)) + if (hasFP(MF)) { adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize - RVFI->getVarArgsSaveSize(), MachineInstr::FrameSetup); + + // Emit ".cfi_def_cfa $fp, 0" + unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa( + nullptr, RI->getDwarfRegNum(FPReg, true), 0)); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); + } } void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, @@ -141,6 +168,7 @@ MachineFrameInfo &MFI = MF.getFrameInfo(); auto *RVFI = MF.getInfo(); DebugLoc DL = MBBI->getDebugLoc(); + const RISCVInstrInfo *TII = STI.getInstrInfo(); unsigned FPReg = getFPReg(STI); unsigned SPReg = getSPReg(STI); @@ -150,19 +178,58 @@ auto LastFrameDestroy = std::prev(MBBI, MFI.getCalleeSavedInfo().size()); uint64_t StackSize = MFI.getStackSize(); + uint64_t FPOffset = StackSize - RVFI->getVarArgsSaveSize(); // Restore the stack pointer using the value of the frame pointer. Only // necessary if the stack pointer was modified, meaning the stack size is // unknown. if (RI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) { assert(hasFP(MF) && "frame pointer should not have been eliminated"); - adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, - -StackSize + RVFI->getVarArgsSaveSize(), + adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, -FPOffset, MachineInstr::FrameDestroy); } + if (hasFP(MF)) { + // To find the instruction restoring FP from stack. + for (auto &I = LastFrameDestroy; I != MBBI; ++I) { + if (I->mayLoad() && I->getOperand(0).isReg()) { + unsigned DestReg = I->getOperand(0).getReg(); + if (DestReg == FPReg) { + // If there is frame pointer, after restoring $fp registers, we + // need adjust CFA to ($sp - FPOffset). + // Emit ".cfi_def_cfa $sp, -FPOffset" + unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa( + nullptr, RI->getDwarfRegNum(SPReg, true), -FPOffset)); + BuildMI(MBB, std::next(I), DL, + TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); + break; + } + } + } + } + + // Add CFI directives for callee-saved registers. + const std::vector &CSI = MFI.getCalleeSavedInfo(); + // Iterate over list of callee-saved registers and emit .cfi_restore + // directives. + for (const auto &Entry : CSI) { + unsigned Reg = Entry.getReg(); + unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestore( + nullptr, RI->getDwarfRegNum(Reg, true))); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); + } + // Deallocate stack adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy); + + // After restoring $sp, we need to adjust CFA to $(sp + 0) + // Emit ".cfi_def_cfa_offset 0" + unsigned CFIIndex = + MF.addFrameInst(MCCFIInstruction::createDefCfaOffset(nullptr, 0)); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); } int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, Index: llvm/trunk/test/CodeGen/RISCV/frame-info.ll =================================================================== --- llvm/trunk/test/CodeGen/RISCV/frame-info.ll +++ llvm/trunk/test/CodeGen/RISCV/frame-info.ll @@ -0,0 +1,66 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 < %s | FileCheck -check-prefix=RV32 %s +; RUN: llc -mtriple=riscv64 < %s | FileCheck -check-prefix=RV64 %s + +define void @foo(i32 signext %size) { +; RV32-LABEL: foo: +; RV32: # %bb.0: # %entry +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw ra, 12(sp) +; RV32-NEXT: sw s0, 8(sp) +; RV32-NEXT: .cfi_offset ra, -4 +; RV32-NEXT: .cfi_offset s0, -8 +; RV32-NEXT: addi s0, sp, 16 +; RV32-NEXT: .cfi_def_cfa s0, 0 +; RV32-NEXT: addi a0, a0, 15 +; RV32-NEXT: andi a0, a0, -16 +; RV32-NEXT: sub a0, sp, a0 +; RV32-NEXT: mv sp, a0 +; RV32-NEXT: call bar +; RV32-NEXT: addi sp, s0, -16 +; RV32-NEXT: lw s0, 8(sp) +; RV32-NEXT: .cfi_def_cfa sp, 16 +; RV32-NEXT: lw ra, 12(sp) +; RV32-NEXT: .cfi_restore ra +; RV32-NEXT: .cfi_restore s0 +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: .cfi_def_cfa_offset 0 +; RV32-NEXT: ret +; +; RV64-LABEL: foo: +; RV64: # %bb.0: # %entry +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: .cfi_def_cfa_offset 16 +; RV64-NEXT: sd ra, 8(sp) +; RV64-NEXT: sd s0, 0(sp) +; RV64-NEXT: .cfi_offset ra, -8 +; RV64-NEXT: .cfi_offset s0, -16 +; RV64-NEXT: addi s0, sp, 16 +; RV64-NEXT: .cfi_def_cfa s0, 0 +; RV64-NEXT: addi a1, zero, 1 +; RV64-NEXT: slli a1, a1, 33 +; RV64-NEXT: addi a1, a1, -16 +; RV64-NEXT: slli a0, a0, 32 +; RV64-NEXT: srli a0, a0, 32 +; RV64-NEXT: addi a0, a0, 15 +; RV64-NEXT: and a0, a0, a1 +; RV64-NEXT: sub a0, sp, a0 +; RV64-NEXT: mv sp, a0 +; RV64-NEXT: call bar +; RV64-NEXT: addi sp, s0, -16 +; RV64-NEXT: ld s0, 0(sp) +; RV64-NEXT: .cfi_def_cfa sp, 16 +; RV64-NEXT: ld ra, 8(sp) +; RV64-NEXT: .cfi_restore ra +; RV64-NEXT: .cfi_restore s0 +; RV64-NEXT: addi sp, sp, 16 +; RV64-NEXT: .cfi_def_cfa_offset 0 +; RV64-NEXT: ret +entry: + %0 = alloca i8, i32 %size, align 16 + call void @bar(i8* nonnull %0) #2 + ret void +} + +declare void @bar(i8*)