Skip to content

Commit 478fce9

Browse files
committed
[LLVM-C] Finish exception instruction bindings - Round 2
Summary: Previous revision caused a leak in the echo test that got caught by the ASAN bots because of missing free of the handlers array and was reverted in r328759. Resubmitting the patch with that correction. Add support for cleanupret, catchret, catchpad, cleanuppad and catchswitch and their associated accessors. Test is modified from SimplifyCFG because it contains many diverse usages of these instructions. Reviewers: whitequark, deadalnix Reviewed By: whitequark Subscribers: llvm-commits, vlad.tsyrklevich Differential Revision: https://reviews.llvm.org/D45100 llvm-svn: 328883
1 parent 5f8c3e8 commit 478fce9

File tree

4 files changed

+261
-10
lines changed

4 files changed

+261
-10
lines changed

llvm/include/llvm-c/Core.h

+73-6
Original file line numberDiff line numberDiff line change
@@ -2555,11 +2555,12 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst);
25552555
/**
25562556
* Obtain the argument count for a call instruction.
25572557
*
2558-
* This expects an LLVMValueRef that corresponds to a llvm::CallInst or
2559-
* llvm::InvokeInst.
2558+
* This expects an LLVMValueRef that corresponds to a llvm::CallInst,
2559+
* llvm::InvokeInst, or llvm:FuncletPadInst.
25602560
*
25612561
* @see llvm::CallInst::getNumArgOperands()
25622562
* @see llvm::InvokeInst::getNumArgOperands()
2563+
* @see llvm::FuncletPadInst::getNumArgOperands()
25632564
*/
25642565
unsigned LLVMGetNumArgOperands(LLVMValueRef Instr);
25652566

@@ -2644,9 +2645,12 @@ LLVMBasicBlockRef LLVMGetNormalDest(LLVMValueRef InvokeInst);
26442645
/**
26452646
* Return the unwind destination basic block.
26462647
*
2647-
* This only works on llvm::InvokeInst instructions.
2648+
* Works on llvm::InvokeInst, llvm::CleanupReturnInst, and
2649+
* llvm::CatchSwitchInst instructions.
26482650
*
26492651
* @see llvm::InvokeInst::getUnwindDest()
2652+
* @see llvm::CleanupReturnInst::getUnwindDest()
2653+
* @see llvm::CatchSwitchInst::getUnwindDest()
26502654
*/
26512655
LLVMBasicBlockRef LLVMGetUnwindDest(LLVMValueRef InvokeInst);
26522656

@@ -2662,9 +2666,12 @@ void LLVMSetNormalDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);
26622666
/**
26632667
* Set the unwind destination basic block.
26642668
*
2665-
* This only works on llvm::InvokeInst instructions.
2669+
* Works on llvm::InvokeInst, llvm::CleanupReturnInst, and
2670+
* llvm::CatchSwitchInst instructions.
26662671
*
26672672
* @see llvm::InvokeInst::setUnwindDest()
2673+
* @see llvm::CleanupReturnInst::setUnwindDest()
2674+
* @see llvm::CatchSwitchInst::setUnwindDest()
26682675
*/
26692676
void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);
26702677

@@ -2893,11 +2900,26 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn,
28932900
LLVMValueRef *Args, unsigned NumArgs,
28942901
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
28952902
const char *Name);
2903+
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);
2904+
2905+
/* Exception Handling */
2906+
LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn);
28962907
LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
28972908
LLVMValueRef PersFn, unsigned NumClauses,
28982909
const char *Name);
2899-
LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn);
2900-
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);
2910+
LLVMValueRef LLVMBuildCleanupRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
2911+
LLVMBasicBlockRef BB);
2912+
LLVMValueRef LLVMBuildCatchRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
2913+
LLVMBasicBlockRef BB);
2914+
LLVMValueRef LLVMBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
2915+
LLVMValueRef *Args, unsigned NumArgs,
2916+
const char *Name);
2917+
LLVMValueRef LLVMBuildCleanupPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
2918+
LLVMValueRef *Args, unsigned NumArgs,
2919+
const char *Name);
2920+
LLVMValueRef LLVMBuildCatchSwitch(LLVMBuilderRef B, LLVMValueRef ParentPad,
2921+
LLVMBasicBlockRef UnwindBB,
2922+
unsigned NumHandlers, const char *Name);
29012923

29022924
/* Add a case to the switch instruction */
29032925
void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal,
@@ -2921,6 +2943,51 @@ LLVMBool LLVMIsCleanup(LLVMValueRef LandingPad);
29212943
/* Set the 'cleanup' flag in the landingpad instruction */
29222944
void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val);
29232945

2946+
/* Add a destination to the catchswitch instruction */
2947+
void LLVMAddHandler(LLVMValueRef CatchSwitch, LLVMBasicBlockRef Dest);
2948+
2949+
/* Get the number of handlers on the catchswitch instruction */
2950+
unsigned LLVMGetNumHandlers(LLVMValueRef CatchSwitch);
2951+
2952+
/**
2953+
* Obtain the basic blocks acting as handlers for a catchswitch instruction.
2954+
*
2955+
* The Handlers parameter should point to a pre-allocated array of
2956+
* LLVMBasicBlockRefs at least LLVMGetNumHandlers() large. On return, the
2957+
* first LLVMGetNumHandlers() entries in the array will be populated
2958+
* with LLVMBasicBlockRef instances.
2959+
*
2960+
* @param CatchSwitch The catchswitch instruction to operate on.
2961+
* @param Handlers Memory address of an array to be filled with basic blocks.
2962+
*/
2963+
void LLVMGetHandlers(LLVMValueRef CatchSwitch, LLVMBasicBlockRef *Handlers);
2964+
2965+
/* Funclets */
2966+
2967+
/* Get the number of funcletpad arguments. */
2968+
LLVMValueRef LLVMGetArgOperand(LLVMValueRef Funclet, unsigned i);
2969+
2970+
/* Set a funcletpad argument at the given index. */
2971+
void LLVMSetArgOperand(LLVMValueRef Funclet, unsigned i, LLVMValueRef value);
2972+
2973+
/**
2974+
* Get the parent catchswitch instruction of a catchpad instruction.
2975+
*
2976+
* This only works on llvm::CatchPadInst instructions.
2977+
*
2978+
* @see llvm::CatchPadInst::getCatchSwitch()
2979+
*/
2980+
LLVMValueRef LLVMGetParentCatchSwitch(LLVMValueRef CatchPad);
2981+
2982+
/**
2983+
* Set the parent catchswitch instruction of a catchpad instruction.
2984+
*
2985+
* This only works on llvm::CatchPadInst instructions.
2986+
*
2987+
* @see llvm::CatchPadInst::setCatchSwitch()
2988+
*/
2989+
void LLVMSetParentCatchSwitch(LLVMValueRef CatchPad, LLVMValueRef CatchSwitch);
2990+
29242991
/* Arithmetic */
29252992
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS,
29262993
const char *Name);

llvm/lib/IR/Core.cpp

+92-2
Original file line numberDiff line numberDiff line change
@@ -2196,12 +2196,15 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst) {
21962196
return nullptr;
21972197
}
21982198

2199-
/*--.. Call and invoke instructions ........................................--*/
2200-
22012199
unsigned LLVMGetNumArgOperands(LLVMValueRef Instr) {
2200+
if (FuncletPadInst *FPI = dyn_cast<FuncletPadInst>(unwrap(Instr))) {
2201+
return FPI->getNumArgOperands();
2202+
}
22022203
return CallSite(unwrap<Instruction>(Instr)).getNumArgOperands();
22032204
}
22042205

2206+
/*--.. Call and invoke instructions ........................................--*/
2207+
22052208
unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr) {
22062209
return CallSite(unwrap<Instruction>(Instr)).getCallingConv();
22072210
}
@@ -2284,6 +2287,11 @@ LLVMBasicBlockRef LLVMGetNormalDest(LLVMValueRef Invoke) {
22842287
}
22852288

22862289
LLVMBasicBlockRef LLVMGetUnwindDest(LLVMValueRef Invoke) {
2290+
if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(unwrap(Invoke))) {
2291+
return wrap(CRI->getUnwindDest());
2292+
} else if (CatchSwitchInst *CSI = dyn_cast<CatchSwitchInst>(unwrap(Invoke))) {
2293+
return wrap(CSI->getUnwindDest());
2294+
}
22872295
return wrap(unwrap<InvokeInst>(Invoke)->getUnwindDest());
22882296
}
22892297

@@ -2292,6 +2300,11 @@ void LLVMSetNormalDest(LLVMValueRef Invoke, LLVMBasicBlockRef B) {
22922300
}
22932301

22942302
void LLVMSetUnwindDest(LLVMValueRef Invoke, LLVMBasicBlockRef B) {
2303+
if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(unwrap(Invoke))) {
2304+
return CRI->setUnwindDest(unwrap(B));
2305+
} else if (CatchSwitchInst *CSI = dyn_cast<CatchSwitchInst>(unwrap(Invoke))) {
2306+
return CSI->setUnwindDest(unwrap(B));
2307+
}
22952308
unwrap<InvokeInst>(Invoke)->setUnwindDest(unwrap(B));
22962309
}
22972310

@@ -2513,10 +2526,53 @@ LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
25132526
return wrap(unwrap(B)->CreateLandingPad(unwrap(Ty), NumClauses, Name));
25142527
}
25152528

2529+
LLVMValueRef LLVMBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
2530+
LLVMValueRef *Args, unsigned NumArgs,
2531+
const char *Name) {
2532+
return wrap(unwrap(B)->CreateCatchPad(unwrap(ParentPad),
2533+
makeArrayRef(unwrap(Args), NumArgs),
2534+
Name));
2535+
}
2536+
2537+
LLVMValueRef LLVMBuildCleanupPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
2538+
LLVMValueRef *Args, unsigned NumArgs,
2539+
const char *Name) {
2540+
if (ParentPad == nullptr) {
2541+
Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
2542+
ParentPad = wrap(Constant::getNullValue(Ty));
2543+
}
2544+
return wrap(unwrap(B)->CreateCleanupPad(unwrap(ParentPad),
2545+
makeArrayRef(unwrap(Args), NumArgs),
2546+
Name));
2547+
}
2548+
25162549
LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn) {
25172550
return wrap(unwrap(B)->CreateResume(unwrap(Exn)));
25182551
}
25192552

2553+
LLVMValueRef LLVMBuildCatchSwitch(LLVMBuilderRef B, LLVMValueRef ParentPad,
2554+
LLVMBasicBlockRef UnwindBB,
2555+
unsigned NumHandlers, const char *Name) {
2556+
if (ParentPad == nullptr) {
2557+
Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
2558+
ParentPad = wrap(Constant::getNullValue(Ty));
2559+
}
2560+
return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(UnwindBB),
2561+
NumHandlers, Name));
2562+
}
2563+
2564+
LLVMValueRef LLVMBuildCatchRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
2565+
LLVMBasicBlockRef BB) {
2566+
return wrap(unwrap(B)->CreateCatchRet(unwrap<CatchPadInst>(CatchPad),
2567+
unwrap(BB)));
2568+
}
2569+
2570+
LLVMValueRef LLVMBuildCleanupRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
2571+
LLVMBasicBlockRef BB) {
2572+
return wrap(unwrap(B)->CreateCleanupRet(unwrap<CleanupPadInst>(CatchPad),
2573+
unwrap(BB)));
2574+
}
2575+
25202576
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef B) {
25212577
return wrap(unwrap(B)->CreateUnreachable());
25222578
}
@@ -2551,6 +2607,40 @@ void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val) {
25512607
unwrap<LandingPadInst>(LandingPad)->setCleanup(Val);
25522608
}
25532609

2610+
void LLVMAddHandler(LLVMValueRef CatchSwitch, LLVMBasicBlockRef Dest) {
2611+
unwrap<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Dest));
2612+
}
2613+
2614+
unsigned LLVMGetNumHandlers(LLVMValueRef CatchSwitch) {
2615+
return unwrap<CatchSwitchInst>(CatchSwitch)->getNumHandlers();
2616+
}
2617+
2618+
void LLVMGetHandlers(LLVMValueRef CatchSwitch, LLVMBasicBlockRef *Handlers) {
2619+
CatchSwitchInst *CSI = unwrap<CatchSwitchInst>(CatchSwitch);
2620+
for (CatchSwitchInst::handler_iterator I = CSI->handler_begin(),
2621+
E = CSI->handler_end(); I != E; ++I)
2622+
*Handlers++ = wrap(*I);
2623+
}
2624+
2625+
LLVMValueRef LLVMGetParentCatchSwitch(LLVMValueRef CatchPad) {
2626+
return wrap(unwrap<CatchPadInst>(CatchPad)->getCatchSwitch());
2627+
}
2628+
2629+
void LLVMSetParentCatchSwitch(LLVMValueRef CatchPad, LLVMValueRef CatchSwitch) {
2630+
unwrap<CatchPadInst>(CatchPad)
2631+
->setCatchSwitch(unwrap<CatchSwitchInst>(CatchSwitch));
2632+
}
2633+
2634+
/*--.. Funclets ...........................................................--*/
2635+
2636+
LLVMValueRef LLVMGetArgOperand(LLVMValueRef Funclet, unsigned i) {
2637+
return wrap(unwrap<FuncletPadInst>(Funclet)->getArgOperand(i));
2638+
}
2639+
2640+
void LLVMSetArgOperand(LLVMValueRef Funclet, unsigned i, LLVMValueRef value) {
2641+
unwrap<FuncletPadInst>(Funclet)->setArgOperand(i, unwrap(value));
2642+
}
2643+
25542644
/*--.. Arithmetic ..........................................................--*/
25552645

25562646
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS,

llvm/test/Bindings/llvm-c/echo.ll

+35
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,38 @@ do:
122122
done:
123123
ret i32 %p
124124
}
125+
126+
declare void @personalityFn()
127+
128+
define void @exn() personality void ()* @personalityFn {
129+
entry:
130+
invoke void @decl()
131+
to label %via.cleanup unwind label %exn.dispatch
132+
via.cleanup:
133+
invoke void @decl()
134+
to label %via.catchswitch unwind label %cleanup.inner
135+
cleanup.inner:
136+
%cp.inner = cleanuppad within none []
137+
cleanupret from %cp.inner unwind label %exn.dispatch
138+
via.catchswitch:
139+
invoke void @decl()
140+
to label %exit unwind label %dispatch.inner
141+
dispatch.inner:
142+
%cs.inner = catchswitch within none [label %pad.inner] unwind label %exn.dispatch
143+
pad.inner:
144+
%catch.inner = catchpad within %cs.inner [i32 0]
145+
catchret from %catch.inner to label %exit
146+
exn.dispatch:
147+
%cs = catchswitch within none [label %pad1, label %pad2] unwind label %cleanup
148+
pad1:
149+
catchpad within %cs [i32 1]
150+
unreachable
151+
pad2:
152+
catchpad within %cs [i32 2]
153+
unreachable
154+
cleanup:
155+
%cp = cleanuppad within none []
156+
cleanupret from %cp unwind to caller
157+
exit:
158+
ret void
159+
}

llvm/tools/llvm-c-test/echo.cpp

+61-2
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ struct TypeCloner {
146146
return LLVMMetadataTypeInContext(Ctx);
147147
case LLVMX86_MMXTypeKind:
148148
return LLVMX86MMXTypeInContext(Ctx);
149-
default:
150-
break;
149+
case LLVMTokenTypeKind:
150+
return LLVMTokenTypeInContext(Ctx);
151151
}
152152

153153
fprintf(stderr, "%d is not a supported typekind\n", Kind);
@@ -311,6 +311,13 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
311311
return LLVMGetUndef(TypeCloner(M).Clone(Cst));
312312
}
313313

314+
// Try null
315+
if (LLVMIsNull(Cst)) {
316+
check_value_kind(Cst, LLVMConstantTokenNoneValueKind);
317+
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
318+
return LLVMConstNull(Ty);
319+
}
320+
314321
// Try float literal
315322
if (LLVMIsAConstantFP(Cst)) {
316323
check_value_kind(Cst, LLVMConstantFPValueKind);
@@ -631,6 +638,58 @@ struct FunCloner {
631638
LLVMSetCleanup(Dst, LLVMIsCleanup(Src));
632639
break;
633640
}
641+
case LLVMCleanupRet: {
642+
LLVMValueRef CatchPad = CloneValue(LLVMGetOperand(Src, 0));
643+
LLVMBasicBlockRef Unwind = nullptr;
644+
if (LLVMBasicBlockRef UDest = LLVMGetUnwindDest(Src))
645+
Unwind = DeclareBB(UDest);
646+
Dst = LLVMBuildCleanupRet(Builder, CatchPad, Unwind);
647+
break;
648+
}
649+
case LLVMCatchRet: {
650+
LLVMValueRef CatchPad = CloneValue(LLVMGetOperand(Src, 0));
651+
LLVMBasicBlockRef SuccBB = DeclareBB(LLVMGetSuccessor(Src, 0));
652+
Dst = LLVMBuildCatchRet(Builder, CatchPad, SuccBB);
653+
break;
654+
}
655+
case LLVMCatchPad: {
656+
LLVMValueRef ParentPad = CloneValue(LLVMGetParentCatchSwitch(Src));
657+
SmallVector<LLVMValueRef, 8> Args;
658+
int ArgCount = LLVMGetNumArgOperands(Src);
659+
for (int i = 0; i < ArgCount; i++)
660+
Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
661+
Dst = LLVMBuildCatchPad(Builder, ParentPad,
662+
Args.data(), ArgCount, Name);
663+
break;
664+
}
665+
case LLVMCleanupPad: {
666+
LLVMValueRef ParentPad = CloneValue(LLVMGetOperand(Src, 0));
667+
SmallVector<LLVMValueRef, 8> Args;
668+
int ArgCount = LLVMGetNumArgOperands(Src);
669+
for (int i = 0; i < ArgCount; i++)
670+
Args.push_back(CloneValue(LLVMGetArgOperand(Src, i)));
671+
Dst = LLVMBuildCleanupPad(Builder, ParentPad,
672+
Args.data(), ArgCount, Name);
673+
break;
674+
}
675+
case LLVMCatchSwitch: {
676+
LLVMValueRef ParentPad = CloneValue(LLVMGetOperand(Src, 0));
677+
LLVMBasicBlockRef UnwindBB = nullptr;
678+
if (LLVMBasicBlockRef UDest = LLVMGetUnwindDest(Src)) {
679+
UnwindBB = DeclareBB(UDest);
680+
}
681+
unsigned NumHandlers = LLVMGetNumHandlers(Src);
682+
Dst = LLVMBuildCatchSwitch(Builder, ParentPad, UnwindBB, NumHandlers, Name);
683+
if (NumHandlers > 0) {
684+
LLVMBasicBlockRef *Handlers = static_cast<LLVMBasicBlockRef*>(
685+
safe_malloc(NumHandlers * sizeof(LLVMBasicBlockRef)));
686+
LLVMGetHandlers(Src, Handlers);
687+
for (unsigned i = 0; i < NumHandlers; i++)
688+
LLVMAddHandler(Dst, DeclareBB(Handlers[i]));
689+
free(Handlers);
690+
}
691+
break;
692+
}
634693
case LLVMExtractValue: {
635694
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
636695
if (LLVMGetNumIndices(Src) != 1)

0 commit comments

Comments
 (0)