Index: include/llvm-c/Core.h =================================================================== --- include/llvm-c/Core.h +++ include/llvm-c/Core.h @@ -1476,6 +1476,11 @@ LLVMValueRef LLVMConstPointerNull(LLVMTypeRef Ty); /** + * Obtain the constant token "none", used in SEH instructions. + */ +LLVMValueRef LLVMConstTokenNone(LLVMContextRef C); + +/** * @defgroup LLVMCCoreValueConstantScalar Scalar constants * * Functions in this group model LLVMValueRef instances that correspond @@ -2827,9 +2832,29 @@ LLVMValueRef *Args, unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, const char *Name); +LLVMValueRef LLVMBuildInvokeInPad(LLVMBuilderRef B, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + LLVMBasicBlockRef Then, + LLVMBasicBlockRef Catch, LLVMValueRef Pad, + const char *Name); LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef PersFn, unsigned NumClauses, const char *Name); +LLVMValueRef LLVMBuildCatchSwitch(LLVMBuilderRef B, LLVMValueRef ParentPad, + LLVMBasicBlockRef UnwindBB, + unsigned NumHandlers, const char *Name); +void LLVMAddHandlerToCatchSwitch(LLVMValueRef CatchSwitch, + LLVMBasicBlockRef HandlerVal); +LLVMValueRef LLVMBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad, + LLVMValueRef *Args, unsigned NumArgs, + const char *Name); +LLVMValueRef LLVMBuildCleanupPad(LLVMBuilderRef B, LLVMValueRef ParentPad, + LLVMValueRef *Args, unsigned NumArgs, + const char *Name); +LLVMValueRef LLVMBuildCatchRet(LLVMBuilderRef B, LLVMValueRef CatchPad, + LLVMBasicBlockRef BB); +LLVMValueRef LLVMBuildCleanupRet(LLVMBuilderRef B, LLVMValueRef CleanupPad, + LLVMBasicBlockRef UnwindBB); LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn); LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef); @@ -3002,6 +3027,9 @@ LLVMValueRef LLVMBuildCall(LLVMBuilderRef, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, const char *Name); +LLVMValueRef LLVMBuildCallInPad(LLVMBuilderRef B, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + LLVMValueRef Pad, const char *Name); LLVMValueRef LLVMBuildSelect(LLVMBuilderRef, LLVMValueRef If, LLVMValueRef Then, LLVMValueRef Else, const char *Name); Index: lib/IR/Core.cpp =================================================================== --- lib/IR/Core.cpp +++ lib/IR/Core.cpp @@ -820,6 +820,11 @@ return wrap(ConstantPointerNull::get(unwrap(Ty))); } +LLVMValueRef LLVMConstTokenNone(LLVMContextRef C) { + LLVMContext &Context = *unwrap(C); + return wrap(ConstantTokenNone::get(Context)); +} + /*--.. Operations on metadata nodes ........................................--*/ LLVMValueRef LLVMMDStringInContext(LLVMContextRef C, const char *Str, @@ -2461,6 +2466,18 @@ Name)); } +LLVMValueRef LLVMBuildInvokeInPad(LLVMBuilderRef B, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + LLVMBasicBlockRef Then, + LLVMBasicBlockRef Catch, + LLVMValueRef Pad, const char *Name) { + SmallVector BundleList; + BundleList.emplace_back("funclet", unwrap(Pad)); + return wrap(unwrap(B)->CreateInvoke(unwrap(Fn), unwrap(Then), unwrap(Catch), + makeArrayRef(unwrap(Args), NumArgs), + BundleList, Name)); +} + LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef PersFn, unsigned NumClauses, const char *Name) { @@ -2477,6 +2494,52 @@ return wrap(unwrap(B)->CreateResume(unwrap(Exn))); } +LLVMValueRef LLVMBuildCatchSwitch(LLVMBuilderRef B, + LLVMValueRef ParentPad, + LLVMBasicBlockRef UnwindBB, + unsigned NumHandlers, + const char *Name) { + return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(UnwindBB), + NumHandlers, Name)); +} + +void LLVMAddHandlerToCatchSwitch(LLVMValueRef CatchSwitch, + LLVMBasicBlockRef handler) { + unwrap(CatchSwitch)->addHandler(unwrap(handler)); +} + +LLVMValueRef LLVMBuildCatchPad(LLVMBuilderRef B, + LLVMValueRef ParentPad, + LLVMValueRef *Args, + unsigned NumArgs, + const char *Name) { + ArrayRef ArgList(unwrap(Args), NumArgs); + return wrap(unwrap(B)->CreateCatchPad(unwrap(ParentPad), ArgList, Name)); +} + +LLVMValueRef LLVMBuildCleanupPad(LLVMBuilderRef B, + LLVMValueRef ParentPad, + LLVMValueRef *Args, + unsigned NumArgs, + const char *Name) { + ArrayRef ArgList(unwrap(Args), NumArgs); + return wrap(unwrap(B)->CreateCleanupPad(unwrap(ParentPad), ArgList, Name)); +} + +LLVMValueRef LLVMBuildCatchRet(LLVMBuilderRef B, + LLVMValueRef CatchPad, + LLVMBasicBlockRef BB) { + return wrap(unwrap(B)->CreateCatchRet(unwrap(CatchPad), + unwrap(BB))); +} + +LLVMValueRef LLVMBuildCleanupRet(LLVMBuilderRef B, + LLVMValueRef CleanupPad, + LLVMBasicBlockRef UnwindBB) { + return wrap(unwrap(B)->CreateCleanupRet(unwrap(CleanupPad), + unwrap(UnwindBB))); +} + LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef B) { return wrap(unwrap(B)->CreateUnreachable()); } @@ -2961,6 +3024,17 @@ Name)); } +LLVMValueRef LLVMBuildCallInPad(LLVMBuilderRef B, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + LLVMValueRef Pad, const char *Name) { + SmallVector BundleList; + BundleList.emplace_back("funclet", unwrap(Pad)); + return wrap(unwrap(B)->CreateCall(unwrap(Fn), + makeArrayRef(unwrap(Args), NumArgs), + BundleList, + Name)); +} + LLVMValueRef LLVMBuildSelect(LLVMBuilderRef B, LLVMValueRef If, LLVMValueRef Then, LLVMValueRef Else, const char *Name) { Index: test/Bindings/llvm-c/seh.ll =================================================================== --- /dev/null +++ test/Bindings/llvm-c/seh.ll @@ -0,0 +1,41 @@ +; RUN: llvm-as < %s | llvm-dis > %t.orig +; RUN: llvm-as < %s | llvm-c-test --echo > %t.echo +; RUN: diff -w %t.orig %t.echo +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc18.0.0" + +define void @g() { + ret void +} + +define void @f2() personality i32 (...)* @__CxxFrameHandler3 { +entry: + %b = alloca i32 + invoke void @g() to label %invoke.cont unwind label %ehcleanup + +invoke.cont: ; preds = %entry + br label %try.cont + +ehcleanup: ; preds = %entry + %0 = cleanuppad within none [] + cleanupret from %0 unwind label %catch.dispatch + +catch.dispatch: ; preds = %ehcleanup + %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1 + +catch: ; preds = %catch.dispatch + %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] + catchret from %1 to label %catchret.dest + +catchret.dest: ; preds = %catch + br label %try.cont + +try.cont: ; preds = %catchret.dest, %invoke.cont + ret void + +ehcleanup.1: + %2 = cleanuppad within none [label %catch] + cleanupret from %2 unwind to caller +} + +declare i32 @__CxxFrameHandler3(...) \ No newline at end of file Index: tools/llvm-c-test/echo.cpp =================================================================== --- tools/llvm-c-test/echo.cpp +++ tools/llvm-c-test/echo.cpp @@ -316,6 +316,19 @@ report_fatal_error("ConstantFP is not supported"); } + // Try a null pointer + if (LLVMIsAConstantPointerNull(Cst)) { + check_value_kind(Cst, LLVMConstantPointerNullValueKind); + LLVMTypeRef Ty = TypeCloner(M).Clone(Cst); + return LLVMConstPointerNull(Ty); + } + + // Try a none token + if (LLVMIsAConstantTokenNone(Cst)) { + check_value_kind(Cst, LLVMConstantTokenNoneValueKind); + return LLVMConstTokenNone(LLVMGetModuleContext(M)); + } + // This kind of constant is not supported if (!LLVMIsAConstantExpr(Cst)) report_fatal_error("Expected a constant expression"); @@ -647,6 +660,62 @@ Dst = LLVMBuildInsertValue(Builder, Agg, V, I, Name); break; } + case LLVMCleanupPad: { + unsigned Operands = LLVMGetNumOperands(Src); + if (Operands == 0) + report_fatal_error("Expected at least one indice"); + unsigned NumArgs = Operands - 1; + LLVMValueRef Parent = CloneValue(LLVMGetOperand(Src, Operands - 1)); + SmallVector Args; + for (unsigned i = 0; i < NumArgs; i++) + Args.push_back(CloneValue(LLVMGetOperand(Src, i))); + Dst = LLVMBuildCleanupPad(Builder, Parent, Args.data(), NumArgs, Name); + break; + } + case LLVMCleanupRet: { + LLVMBasicBlockRef Unwind = nullptr; + if (LLVMGetNumOperands(Src) > 1) { + LLVMValueRef Unval = LLVMGetOperand(Src, 1); + Unwind = DeclareBB(LLVMValueAsBasicBlock(Unval)); + } + LLVMValueRef Cval = CloneValue(LLVMGetOperand(Src, 0)); + Dst = LLVMBuildCleanupRet(Builder, Cval, Unwind); + break; + } + case LLVMCatchSwitch: { + LLVMValueRef Unval = LLVMGetOperand(Src, 1); + LLVMBasicBlockRef Unwind = DeclareBB(LLVMValueAsBasicBlock(Unval)); + if (LLVMGetNumOperands(Src) < 2) + report_fatal_error("Expected at least two operands"); + unsigned NumHandlers = LLVMGetNumOperands(Src) - 2; + LLVMValueRef Parent = CloneValue(LLVMGetOperand(Src, 0)); + Dst = LLVMBuildCatchSwitch(Builder, Parent, Unwind, NumHandlers, Name); + for (unsigned i = 0; i < NumHandlers; i++) { + LLVMBasicBlockRef BB = LLVMValueAsBasicBlock(LLVMGetOperand(Src, + i+2)); + LLVMAddHandlerToCatchSwitch(Dst, DeclareBB(BB)); + } + break; + } + case LLVMCatchPad: { + unsigned Operands = LLVMGetNumOperands(Src); + if (Operands == 0) + report_fatal_error("Expected at least one indice"); + unsigned NumArgs = Operands - 1; + LLVMValueRef Parent = CloneValue(LLVMGetOperand(Src, Operands - 1)); + SmallVector Args; + for (unsigned i = 0; i < NumArgs; i++) + Args.push_back(CloneValue(LLVMGetOperand(Src, i))); + Dst = LLVMBuildCatchPad(Builder, Parent, Args.data(), NumArgs, Name); + break; + } + case LLVMCatchRet: { + LLVMValueRef CatchPad = CloneValue(LLVMGetOperand(Src, 0)); + LLVMValueRef NxtVal = LLVMGetOperand(Src, 1); + LLVMBasicBlockRef Successor = DeclareBB(LLVMValueAsBasicBlock(NxtVal)); + Dst = LLVMBuildCatchRet(Builder, CatchPad, Successor); + break; + } default: break; }