mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 21:00:29 +00:00
Add test case for C++ exception handling and fix the following mistakes in MipsFrameLowering::emitPrologue:
- cfi directives are not inserted at the right location or in the right order. - The source MachineLocation for the cfi directive that changes the cfa register to $fp should be MachineLocation::VirtualFP. - A PROLOG_LABEL that marks the beginning of cfi_offset directives for callee-saved register is emitted even when no callee-saved registers are saved. - When a callee-saved double precision register is saved, two cfi_offset directives, one for each of the paired single precision registers, should be emitted. llvm-svn: 132703
This commit is contained in:
parent
6575812c48
commit
fbeb14925f
@ -173,6 +173,10 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
// No need to allocate space on the stack.
|
||||
if (StackSize == 0 && !MFI->adjustsStack()) return;
|
||||
|
||||
MachineModuleInfo &MMI = MF.getMMI();
|
||||
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
||||
MachineLocation DstML, SrcML;
|
||||
|
||||
// Adjust stack : addi sp, sp, (-imm)
|
||||
ATUsed = expandRegLargeImmPair(Mips::SP, -StackSize, NewReg, NewImm, MBB,
|
||||
MBBI);
|
||||
@ -183,49 +187,75 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
if (ATUsed)
|
||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO));
|
||||
|
||||
// emit ".cfi_def_cfa_offset StackSize"
|
||||
MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
|
||||
BuildMI(MBB, MBBI, dl,
|
||||
TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel);
|
||||
DstML = MachineLocation(MachineLocation::VirtualFP);
|
||||
SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize);
|
||||
Moves.push_back(MachineMove(AdjustSPLabel, DstML, SrcML));
|
||||
|
||||
// Find the instruction past the last instruction that saves a callee-saved
|
||||
// register to the stack.
|
||||
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
||||
|
||||
for (unsigned i = 0; i < CSI.size(); ++i)
|
||||
++MBBI;
|
||||
|
||||
if (CSI.size()) {
|
||||
for (unsigned i = 0; i < CSI.size(); ++i)
|
||||
++MBBI;
|
||||
|
||||
// Iterate over list of callee-saved registers and emit .cfi_offset directives.
|
||||
MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol();
|
||||
BuildMI(MBB, MBBI, dl,
|
||||
TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel);
|
||||
|
||||
for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
|
||||
E = CSI.end(); I != E; ++I) {
|
||||
int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
|
||||
unsigned Reg = I->getReg();
|
||||
|
||||
// If Reg is a double precision register, emit two cfa_offsets,
|
||||
// one for each of the paired single precision registers.
|
||||
if (Mips::AFGR64RegisterClass->contains(Reg)) {
|
||||
const unsigned *SubRegs = RegInfo->getSubRegisters(Reg);
|
||||
MachineLocation DstML0(MachineLocation::VirtualFP, Offset);
|
||||
MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4);
|
||||
MachineLocation SrcML0(*SubRegs);
|
||||
MachineLocation SrcML1(*(SubRegs + 1));
|
||||
|
||||
if (!STI.isLittle())
|
||||
std::swap(SrcML0, SrcML1);
|
||||
|
||||
Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0));
|
||||
Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1));
|
||||
}
|
||||
else {
|
||||
// Reg is either in CPURegs or FGR32.
|
||||
DstML = MachineLocation(MachineLocation::VirtualFP, Offset);
|
||||
SrcML = MachineLocation(Reg);
|
||||
Moves.push_back(MachineMove(CSLabel, DstML, SrcML));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if framepointer enabled, set it to point to the stack pointer.
|
||||
if (hasFP(MF))
|
||||
if (hasFP(MF)) {
|
||||
// Insert instruction "move $fp, $sp" at this location.
|
||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::FP)
|
||||
.addReg(Mips::SP).addReg(Mips::ZERO);
|
||||
|
||||
// emit ".cfi_def_cfa_register $fp"
|
||||
MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol();
|
||||
BuildMI(MBB, MBBI, dl,
|
||||
TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel);
|
||||
DstML = MachineLocation(Mips::FP);
|
||||
SrcML = MachineLocation(MachineLocation::VirtualFP);
|
||||
Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML));
|
||||
}
|
||||
|
||||
// Restore GP from the saved stack location
|
||||
if (MipsFI->needGPSaveRestore())
|
||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE))
|
||||
.addImm(MFI->getObjectOffset(MipsFI->getGPFI()));
|
||||
|
||||
// EH Frame infomation.
|
||||
MachineModuleInfo &MMI = MF.getMMI();
|
||||
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
||||
MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol();
|
||||
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(FrameLabel);
|
||||
|
||||
if (hasFP(MF)) {
|
||||
MachineLocation SPDst(Mips::FP);
|
||||
MachineLocation SPSrc(Mips::SP);
|
||||
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
||||
}
|
||||
|
||||
if (StackSize) {
|
||||
MachineLocation SPDst(MachineLocation::VirtualFP);
|
||||
MachineLocation SPSrc(MachineLocation::VirtualFP, -StackSize);
|
||||
Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
|
||||
}
|
||||
|
||||
for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
|
||||
E = CSI.end(); I != E; ++I) {
|
||||
int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
|
||||
MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
|
||||
MachineLocation CSSrc(I->getReg());
|
||||
Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc));
|
||||
}
|
||||
}
|
||||
|
||||
void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
|
78
test/CodeGen/Mips/eh.ll
Normal file
78
test/CodeGen/Mips/eh.ll
Normal file
@ -0,0 +1,78 @@
|
||||
; RUN: llc < %s -march=mipsel -mcpu=4ke | FileCheck %s -check-prefix=CHECK-EL
|
||||
; RUN: llc < %s -march=mips -mcpu=4ke | FileCheck %s -check-prefix=CHECK-EB
|
||||
|
||||
@g1 = global double 0.000000e+00, align 8
|
||||
@_ZTId = external constant i8*
|
||||
|
||||
define void @_Z1fd(double %i2) {
|
||||
entry:
|
||||
; CHECK-EL: addiu $sp, $sp
|
||||
; CHECK-EL: .cfi_def_cfa_offset
|
||||
; CHECK-EL: sdc1 $f20
|
||||
; CHECK-EL: sw $ra
|
||||
; CHECK-EL: sw $17
|
||||
; CHECK-EL: sw $16
|
||||
; CHECK-EL: .cfi_offset 52, -8
|
||||
; CHECK-EL: .cfi_offset 53, -4
|
||||
; CHECK-EB: .cfi_offset 53, -8
|
||||
; CHECK-EB: .cfi_offset 52, -4
|
||||
; CHECK-EL: .cfi_offset 31, -12
|
||||
; CHECK-EL: .cfi_offset 17, -16
|
||||
; CHECK-EL: .cfi_offset 16, -20
|
||||
; CHECK-EL: .cprestore
|
||||
|
||||
%exception = tail call i8* @__cxa_allocate_exception(i32 8) nounwind
|
||||
%0 = bitcast i8* %exception to double*
|
||||
store double 3.200000e+00, double* %0, align 8, !tbaa !0
|
||||
invoke void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTId to i8*), i8* null) noreturn
|
||||
to label %unreachable unwind label %lpad
|
||||
|
||||
lpad: ; preds = %entry
|
||||
; CHECK-EL: # %lpad
|
||||
; CHECK-EL: lw $gp
|
||||
; CHECK-EL: beq $5
|
||||
|
||||
%exn = tail call i8* @llvm.eh.exception() nounwind
|
||||
%eh.selector = tail call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %exn, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTId to i8*)) nounwind
|
||||
%1 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*)) nounwind
|
||||
%2 = icmp eq i32 %eh.selector, %1
|
||||
br i1 %2, label %catch, label %eh.resume
|
||||
|
||||
catch: ; preds = %lpad
|
||||
%3 = tail call i8* @__cxa_begin_catch(i8* %exn) nounwind
|
||||
%4 = bitcast i8* %3 to double*
|
||||
%exn.scalar = load double* %4, align 8
|
||||
%add = fadd double %exn.scalar, %i2
|
||||
store double %add, double* @g1, align 8, !tbaa !0
|
||||
tail call void @__cxa_end_catch() nounwind
|
||||
ret void
|
||||
|
||||
eh.resume: ; preds = %lpad
|
||||
tail call void @llvm.eh.resume(i8* %exn, i32 %eh.selector) noreturn
|
||||
unreachable
|
||||
|
||||
unreachable: ; preds = %entry
|
||||
unreachable
|
||||
}
|
||||
|
||||
declare i8* @__cxa_allocate_exception(i32)
|
||||
|
||||
declare i8* @llvm.eh.exception() nounwind readonly
|
||||
|
||||
declare i32 @__gxx_personality_v0(...)
|
||||
|
||||
declare i32 @llvm.eh.selector(i8*, i8*, ...) nounwind
|
||||
|
||||
declare i32 @llvm.eh.typeid.for(i8*) nounwind
|
||||
|
||||
declare void @llvm.eh.resume(i8*, i32)
|
||||
|
||||
declare void @__cxa_throw(i8*, i8*, i8*)
|
||||
|
||||
declare i8* @__cxa_begin_catch(i8*)
|
||||
|
||||
declare void @__cxa_end_catch()
|
||||
|
||||
!0 = metadata !{metadata !"double", metadata !1}
|
||||
!1 = metadata !{metadata !"omnipotent char", metadata !2}
|
||||
!2 = metadata !{metadata !"Simple C/C++ TBAA", null}
|
Loading…
Reference in New Issue
Block a user