/// imagerel32 LabelStart;
/// imagerel32 LabelEnd;
/// imagerel32 FilterOrFinally; // One means catch-all.
-/// imagerel32 LabelLPad; // Zero means __finally.
+/// imagerel32 ExceptOrNull; // Zero means __finally.
/// } Entries[NumEntries];
/// };
void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {
// If this invoke ends a previous one, emit all the actions for this
// state.
- if (LastEHState != -1) {
- assert(LastBeginLabel && LastEndLabel);
- for (int State = LastEHState; State != -1;) {
- SEHUnwindMapEntry &UME = FuncInfo.SEHUnwindMap[State];
- const MCExpr *FilterOrFinally;
- const MCExpr *ExceptOrNull;
- auto *Handler = UME.Handler.get<MachineBasicBlock *>();
- if (UME.IsFinally) {
- FilterOrFinally =
- create32bitRef(getMCSymbolForMBBOrGV(Asm, Handler));
- ExceptOrNull = MCConstantExpr::create(0, Ctx);
- } else {
- // For an except, the filter can be 1 (catch-all) or a function
- // label.
- FilterOrFinally = UME.Filter ? create32bitRef(UME.Filter)
- : MCConstantExpr::create(1, Ctx);
- ExceptOrNull = create32bitRef(Handler->getSymbol());
- }
-
- OS.EmitValue(getLabelPlusOne(LastBeginLabel), 4);
- OS.EmitValue(getLabelPlusOne(LastEndLabel), 4);
- OS.EmitValue(FilterOrFinally, 4);
- OS.EmitValue(ExceptOrNull, 4);
-
- State = UME.ToState;
- }
- }
+ if (LastEHState != -1)
+ emitSEHActionsForRange(FuncInfo, LastBeginLabel, LastEndLabel,
+ LastEHState);
LastBeginLabel = I.BeginLabel;
LastEndLabel = I.EndLabel;
LastEHState = I.State;
}
}
+
+ if (LastEndLabel)
+ emitSEHActionsForRange(FuncInfo, LastBeginLabel, LastEndLabel,
+ LastEHState);
+
OS.EmitLabel(TableEnd);
return;
}
}
}
+void WinException::emitSEHActionsForRange(WinEHFuncInfo &FuncInfo,
+ MCSymbol *BeginLabel,
+ MCSymbol *EndLabel, int State) {
+ auto &OS = *Asm->OutStreamer;
+ MCContext &Ctx = Asm->OutContext;
+
+ assert(BeginLabel && EndLabel);
+ while (State != -1) {
+ // struct Entry {
+ // imagerel32 LabelStart;
+ // imagerel32 LabelEnd;
+ // imagerel32 FilterOrFinally; // One means catch-all.
+ // imagerel32 ExceptOrNull; // Zero means __finally.
+ // };
+ SEHUnwindMapEntry &UME = FuncInfo.SEHUnwindMap[State];
+ const MCExpr *FilterOrFinally;
+ const MCExpr *ExceptOrNull;
+ auto *Handler = UME.Handler.get<MachineBasicBlock *>();
+ if (UME.IsFinally) {
+ FilterOrFinally = create32bitRef(getMCSymbolForMBBOrGV(Asm, Handler));
+ ExceptOrNull = MCConstantExpr::create(0, Ctx);
+ } else {
+ // For an except, the filter can be 1 (catch-all) or a function
+ // label.
+ FilterOrFinally = UME.Filter ? create32bitRef(UME.Filter)
+ : MCConstantExpr::create(1, Ctx);
+ ExceptOrNull = create32bitRef(Handler->getSymbol());
+ }
+
+ OS.EmitValue(getLabelPlusOne(BeginLabel), 4);
+ OS.EmitValue(getLabelPlusOne(EndLabel), 4);
+ OS.EmitValue(FilterOrFinally, 4);
+ OS.EmitValue(ExceptOrNull, 4);
+
+ assert(UME.ToState < State && "states should decrease");
+ State = UME.ToState;
+ }
+}
+
void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
const Function *F = MF->getFunction();
auto &OS = *Asm->OutStreamer;
void emitCSpecificHandlerTable(const MachineFunction *MF);
+ void emitSEHActionsForRange(WinEHFuncInfo &FuncInfo, MCSymbol *BeginLabel,
+ MCSymbol *EndLabel, int State);
+
/// Emit the EH table data for 32-bit and 64-bit functions using
/// the __CxxFrameHandler3 personality.
void emitCXXFrameHandler3Table(const MachineFunction *MF);
@str = linkonce_odr unnamed_addr constant [27 x i8] c"GetExceptionCode(): 0x%lx\0A\00", align 1
+declare i32 @llvm.eh.exceptioncode(token)
declare i32 @__C_specific_handler(...)
declare void @crash()
declare i32 @printf(i8* nocapture readonly, ...) nounwind
invoke void @crash()
to label %__try.cont unwind label %lpad
-lpad:
- %0 = landingpad { i8*, i32 }
- catch i8* null
- %1 = extractvalue { i8*, i32 } %0, 0
- %2 = ptrtoint i8* %1 to i64
- %3 = trunc i64 %2 to i32
- call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %3)
- br label %__try.cont
-
__try.cont:
ret i32 0
-eh.resume:
- resume { i8*, i32 } %0
+lpad:
+ %p = catchpad [i8* null, i32 64, i8* null]
+ to label %catchall unwind label %endpad
+
+catchall:
+ %code = call i32 @llvm.eh.exceptioncode(token %p)
+ call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %code)
+ catchret %p to label %__try.cont
+
+endpad:
+ catchendpad unwind to caller
}
; Check that we can get the exception code from eax to the printf.
; CHECK-LABEL: main:
; CHECK: callq crash
; CHECK: retq
-; CHECK: # Block address taken
+; CHECK: .LBB0_2: # %lpad
+; CHECK: # %catchall
; CHECK: leaq str(%rip), %rcx
; CHECK: movl %eax, %edx
; CHECK: callq printf
; CHECK: .seh_handlerdata
-; CHECK-NEXT: .text
-; CHECK-NEXT: .Ltmp{{[0-9]+}}
-; CHECK-NEXT: .seh_endproc
-; CHECK-NEXT: .section .xdata,"dr"
-; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
+; CHECK-NEXT: .Llsda_begin0:
; CHECK-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL
; CHECK-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL+1
; CHECK-NEXT: .long 1
-; CHECK-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL
+; CHECK-NEXT: .long .LBB0_2@IMGREL
+; CHECK-NEXT: .Llsda_end0:
; CHECK: .seh_handlerdata
; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
; CHECK-NEXT: .Llsda_begin0:
-; CHECK-NEXT: .long .Ltmp0@IMGREL
+; CHECK-NEXT: .long .Ltmp0@IMGREL+1
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
; CHECK-NEXT: .long 1
; CHECK-NEXT: .long .LBB1_[[except1bb]]@IMGREL
-; CHECK-NEXT: .long .Ltmp0@IMGREL
+; CHECK-NEXT: .long .Ltmp0@IMGREL+1
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
; CHECK-NEXT: .long .LBB1_[[except2bb]]@IMGREL
-; CHECK-NEXT: .long .Ltmp2@IMGREL
+; CHECK-NEXT: .long .Ltmp2@IMGREL+1
; CHECK-NEXT: .long .Ltmp3@IMGREL+1
; CHECK-NEXT: .long "?dtor$[[finbb:[0-9]+]]@?0?main@4HA"@IMGREL
; CHECK-NEXT: .long 0
-; CHECK-NEXT: .long .Ltmp2@IMGREL
+; CHECK-NEXT: .long .Ltmp2@IMGREL+1
; CHECK-NEXT: .long .Ltmp3@IMGREL+1
; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
; CHECK-NEXT: .long .LBB1_6@IMGREL
+; CHECK-NEXT: .long .Ltmp6@IMGREL+1
+; CHECK-NEXT: .long .Ltmp5@IMGREL+1
+; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
+; CHECK-NEXT: .long .LBB1_6@IMGREL
; CHECK-NEXT: .Llsda_end0:
; CHECK: .text