Skip to content

Commit

Permalink
[LLVM-C] Finish exception instruction bindings - Round 2
Browse files Browse the repository at this point in the history
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
  • Loading branch information
CodaFi committed Mar 30, 2018
1 parent 5f8c3e8 commit 478fce9
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 10 deletions.
79 changes: 73 additions & 6 deletions llvm/include/llvm-c/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -2555,11 +2555,12 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst);
/**
* Obtain the argument count for a call instruction.
*
* This expects an LLVMValueRef that corresponds to a llvm::CallInst or
* llvm::InvokeInst.
* This expects an LLVMValueRef that corresponds to a llvm::CallInst,
* llvm::InvokeInst, or llvm:FuncletPadInst.
*
* @see llvm::CallInst::getNumArgOperands()
* @see llvm::InvokeInst::getNumArgOperands()
* @see llvm::FuncletPadInst::getNumArgOperands()
*/
unsigned LLVMGetNumArgOperands(LLVMValueRef Instr);

Expand Down Expand Up @@ -2644,9 +2645,12 @@ LLVMBasicBlockRef LLVMGetNormalDest(LLVMValueRef InvokeInst);
/**
* Return the unwind destination basic block.
*
* This only works on llvm::InvokeInst instructions.
* Works on llvm::InvokeInst, llvm::CleanupReturnInst, and
* llvm::CatchSwitchInst instructions.
*
* @see llvm::InvokeInst::getUnwindDest()
* @see llvm::CleanupReturnInst::getUnwindDest()
* @see llvm::CatchSwitchInst::getUnwindDest()
*/
LLVMBasicBlockRef LLVMGetUnwindDest(LLVMValueRef InvokeInst);

Expand All @@ -2662,9 +2666,12 @@ void LLVMSetNormalDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);
/**
* Set the unwind destination basic block.
*
* This only works on llvm::InvokeInst instructions.
* Works on llvm::InvokeInst, llvm::CleanupReturnInst, and
* llvm::CatchSwitchInst instructions.
*
* @see llvm::InvokeInst::setUnwindDest()
* @see llvm::CleanupReturnInst::setUnwindDest()
* @see llvm::CatchSwitchInst::setUnwindDest()
*/
void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B);

Expand Down Expand Up @@ -2893,11 +2900,26 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
const char *Name);
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);

/* Exception Handling */
LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn);
LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef PersFn, unsigned NumClauses,
const char *Name);
LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn);
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);
LLVMValueRef LLVMBuildCleanupRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
LLVMBasicBlockRef BB);
LLVMValueRef LLVMBuildCatchRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
LLVMBasicBlockRef BB);
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 LLVMBuildCatchSwitch(LLVMBuilderRef B, LLVMValueRef ParentPad,
LLVMBasicBlockRef UnwindBB,
unsigned NumHandlers, const char *Name);

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

/* Add a destination to the catchswitch instruction */
void LLVMAddHandler(LLVMValueRef CatchSwitch, LLVMBasicBlockRef Dest);

/* Get the number of handlers on the catchswitch instruction */
unsigned LLVMGetNumHandlers(LLVMValueRef CatchSwitch);

/**
* Obtain the basic blocks acting as handlers for a catchswitch instruction.
*
* The Handlers parameter should point to a pre-allocated array of
* LLVMBasicBlockRefs at least LLVMGetNumHandlers() large. On return, the
* first LLVMGetNumHandlers() entries in the array will be populated
* with LLVMBasicBlockRef instances.
*
* @param CatchSwitch The catchswitch instruction to operate on.
* @param Handlers Memory address of an array to be filled with basic blocks.
*/
void LLVMGetHandlers(LLVMValueRef CatchSwitch, LLVMBasicBlockRef *Handlers);

/* Funclets */

/* Get the number of funcletpad arguments. */
LLVMValueRef LLVMGetArgOperand(LLVMValueRef Funclet, unsigned i);

/* Set a funcletpad argument at the given index. */
void LLVMSetArgOperand(LLVMValueRef Funclet, unsigned i, LLVMValueRef value);

/**
* Get the parent catchswitch instruction of a catchpad instruction.
*
* This only works on llvm::CatchPadInst instructions.
*
* @see llvm::CatchPadInst::getCatchSwitch()
*/
LLVMValueRef LLVMGetParentCatchSwitch(LLVMValueRef CatchPad);

/**
* Set the parent catchswitch instruction of a catchpad instruction.
*
* This only works on llvm::CatchPadInst instructions.
*
* @see llvm::CatchPadInst::setCatchSwitch()
*/
void LLVMSetParentCatchSwitch(LLVMValueRef CatchPad, LLVMValueRef CatchSwitch);

/* Arithmetic */
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS,
const char *Name);
Expand Down
94 changes: 92 additions & 2 deletions llvm/lib/IR/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2196,12 +2196,15 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst) {
return nullptr;
}

/*--.. Call and invoke instructions ........................................--*/

unsigned LLVMGetNumArgOperands(LLVMValueRef Instr) {
if (FuncletPadInst *FPI = dyn_cast<FuncletPadInst>(unwrap(Instr))) {
return FPI->getNumArgOperands();
}
return CallSite(unwrap<Instruction>(Instr)).getNumArgOperands();
}

/*--.. Call and invoke instructions ........................................--*/

unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr) {
return CallSite(unwrap<Instruction>(Instr)).getCallingConv();
}
Expand Down Expand Up @@ -2284,6 +2287,11 @@ LLVMBasicBlockRef LLVMGetNormalDest(LLVMValueRef Invoke) {
}

LLVMBasicBlockRef LLVMGetUnwindDest(LLVMValueRef Invoke) {
if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(unwrap(Invoke))) {
return wrap(CRI->getUnwindDest());
} else if (CatchSwitchInst *CSI = dyn_cast<CatchSwitchInst>(unwrap(Invoke))) {
return wrap(CSI->getUnwindDest());
}
return wrap(unwrap<InvokeInst>(Invoke)->getUnwindDest());
}

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

void LLVMSetUnwindDest(LLVMValueRef Invoke, LLVMBasicBlockRef B) {
if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(unwrap(Invoke))) {
return CRI->setUnwindDest(unwrap(B));
} else if (CatchSwitchInst *CSI = dyn_cast<CatchSwitchInst>(unwrap(Invoke))) {
return CSI->setUnwindDest(unwrap(B));
}
unwrap<InvokeInst>(Invoke)->setUnwindDest(unwrap(B));
}

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

LLVMValueRef LLVMBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
LLVMValueRef *Args, unsigned NumArgs,
const char *Name) {
return wrap(unwrap(B)->CreateCatchPad(unwrap(ParentPad),
makeArrayRef(unwrap(Args), NumArgs),
Name));
}

LLVMValueRef LLVMBuildCleanupPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
LLVMValueRef *Args, unsigned NumArgs,
const char *Name) {
if (ParentPad == nullptr) {
Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
ParentPad = wrap(Constant::getNullValue(Ty));
}
return wrap(unwrap(B)->CreateCleanupPad(unwrap(ParentPad),
makeArrayRef(unwrap(Args), NumArgs),
Name));
}

LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn) {
return wrap(unwrap(B)->CreateResume(unwrap(Exn)));
}

LLVMValueRef LLVMBuildCatchSwitch(LLVMBuilderRef B, LLVMValueRef ParentPad,
LLVMBasicBlockRef UnwindBB,
unsigned NumHandlers, const char *Name) {
if (ParentPad == nullptr) {
Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
ParentPad = wrap(Constant::getNullValue(Ty));
}
return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(UnwindBB),
NumHandlers, Name));
}

LLVMValueRef LLVMBuildCatchRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
LLVMBasicBlockRef BB) {
return wrap(unwrap(B)->CreateCatchRet(unwrap<CatchPadInst>(CatchPad),
unwrap(BB)));
}

LLVMValueRef LLVMBuildCleanupRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
LLVMBasicBlockRef BB) {
return wrap(unwrap(B)->CreateCleanupRet(unwrap<CleanupPadInst>(CatchPad),
unwrap(BB)));
}

LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef B) {
return wrap(unwrap(B)->CreateUnreachable());
}
Expand Down Expand Up @@ -2551,6 +2607,40 @@ void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val) {
unwrap<LandingPadInst>(LandingPad)->setCleanup(Val);
}

void LLVMAddHandler(LLVMValueRef CatchSwitch, LLVMBasicBlockRef Dest) {
unwrap<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Dest));
}

unsigned LLVMGetNumHandlers(LLVMValueRef CatchSwitch) {
return unwrap<CatchSwitchInst>(CatchSwitch)->getNumHandlers();
}

void LLVMGetHandlers(LLVMValueRef CatchSwitch, LLVMBasicBlockRef *Handlers) {
CatchSwitchInst *CSI = unwrap<CatchSwitchInst>(CatchSwitch);
for (CatchSwitchInst::handler_iterator I = CSI->handler_begin(),
E = CSI->handler_end(); I != E; ++I)
*Handlers++ = wrap(*I);
}

LLVMValueRef LLVMGetParentCatchSwitch(LLVMValueRef CatchPad) {
return wrap(unwrap<CatchPadInst>(CatchPad)->getCatchSwitch());
}

void LLVMSetParentCatchSwitch(LLVMValueRef CatchPad, LLVMValueRef CatchSwitch) {
unwrap<CatchPadInst>(CatchPad)
->setCatchSwitch(unwrap<CatchSwitchInst>(CatchSwitch));
}

/*--.. Funclets ...........................................................--*/

LLVMValueRef LLVMGetArgOperand(LLVMValueRef Funclet, unsigned i) {
return wrap(unwrap<FuncletPadInst>(Funclet)->getArgOperand(i));
}

void LLVMSetArgOperand(LLVMValueRef Funclet, unsigned i, LLVMValueRef value) {
unwrap<FuncletPadInst>(Funclet)->setArgOperand(i, unwrap(value));
}

/*--.. Arithmetic ..........................................................--*/

LLVMValueRef LLVMBuildAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS,
Expand Down
35 changes: 35 additions & 0 deletions llvm/test/Bindings/llvm-c/echo.ll
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,38 @@ do:
done:
ret i32 %p
}

declare void @personalityFn()

define void @exn() personality void ()* @personalityFn {
entry:
invoke void @decl()
to label %via.cleanup unwind label %exn.dispatch
via.cleanup:
invoke void @decl()
to label %via.catchswitch unwind label %cleanup.inner
cleanup.inner:
%cp.inner = cleanuppad within none []
cleanupret from %cp.inner unwind label %exn.dispatch
via.catchswitch:
invoke void @decl()
to label %exit unwind label %dispatch.inner
dispatch.inner:
%cs.inner = catchswitch within none [label %pad.inner] unwind label %exn.dispatch
pad.inner:
%catch.inner = catchpad within %cs.inner [i32 0]
catchret from %catch.inner to label %exit
exn.dispatch:
%cs = catchswitch within none [label %pad1, label %pad2] unwind label %cleanup
pad1:
catchpad within %cs [i32 1]
unreachable
pad2:
catchpad within %cs [i32 2]
unreachable
cleanup:
%cp = cleanuppad within none []
cleanupret from %cp unwind to caller
exit:
ret void
}
63 changes: 61 additions & 2 deletions llvm/tools/llvm-c-test/echo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ struct TypeCloner {
return LLVMMetadataTypeInContext(Ctx);
case LLVMX86_MMXTypeKind:
return LLVMX86MMXTypeInContext(Ctx);
default:
break;
case LLVMTokenTypeKind:
return LLVMTokenTypeInContext(Ctx);
}

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

// Try null
if (LLVMIsNull(Cst)) {
check_value_kind(Cst, LLVMConstantTokenNoneValueKind);
LLVMTypeRef Ty = TypeCloner(M).Clone(Cst);
return LLVMConstNull(Ty);
}

// Try float literal
if (LLVMIsAConstantFP(Cst)) {
check_value_kind(Cst, LLVMConstantFPValueKind);
Expand Down Expand Up @@ -631,6 +638,58 @@ struct FunCloner {
LLVMSetCleanup(Dst, LLVMIsCleanup(Src));
break;
}
case LLVMCleanupRet: {
LLVMValueRef CatchPad = CloneValue(LLVMGetOperand(Src, 0));
LLVMBasicBlockRef Unwind = nullptr;
if (LLVMBasicBlockRef UDest = LLVMGetUnwindDest(Src))
Unwind = DeclareBB(UDest);
Dst = LLVMBuildCleanupRet(Builder, CatchPad, Unwind);
break;
}
case LLVMCatchRet: {
LLVMValueRef CatchPad = CloneValue(LLVMGetOperand(Src, 0));
LLVMBasicBlockRef SuccBB = DeclareBB(LLVMGetSuccessor(Src, 0));
Dst = LLVMBuildCatchRet(Builder, CatchPad, SuccBB);
break;
}
case LLVMCatchPad: {
LLVMValueRef ParentPad = CloneValue(LLVMGetParentCatchSwitch(Src));
SmallVector<LLVMValueRef, 8> Args;
int ArgCount = LLVMGetNumArgOperands(Src);
for (int i = 0; i < ArgCount; i++)
Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
Dst = LLVMBuildCatchPad(Builder, ParentPad,
Args.data(), ArgCount, Name);
break;
}
case LLVMCleanupPad: {
LLVMValueRef ParentPad = CloneValue(LLVMGetOperand(Src, 0));
SmallVector<LLVMValueRef, 8> Args;
int ArgCount = LLVMGetNumArgOperands(Src);
for (int i = 0; i < ArgCount; i++)
Args.push_back(CloneValue(LLVMGetArgOperand(Src, i)));
Dst = LLVMBuildCleanupPad(Builder, ParentPad,
Args.data(), ArgCount, Name);
break;
}
case LLVMCatchSwitch: {
LLVMValueRef ParentPad = CloneValue(LLVMGetOperand(Src, 0));
LLVMBasicBlockRef UnwindBB = nullptr;
if (LLVMBasicBlockRef UDest = LLVMGetUnwindDest(Src)) {
UnwindBB = DeclareBB(UDest);
}
unsigned NumHandlers = LLVMGetNumHandlers(Src);
Dst = LLVMBuildCatchSwitch(Builder, ParentPad, UnwindBB, NumHandlers, Name);
if (NumHandlers > 0) {
LLVMBasicBlockRef *Handlers = static_cast<LLVMBasicBlockRef*>(
safe_malloc(NumHandlers * sizeof(LLVMBasicBlockRef)));
LLVMGetHandlers(Src, Handlers);
for (unsigned i = 0; i < NumHandlers; i++)
LLVMAddHandler(Dst, DeclareBB(Handlers[i]));
free(Handlers);
}
break;
}
case LLVMExtractValue: {
LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0));
if (LLVMGetNumIndices(Src) != 1)
Expand Down

0 comments on commit 478fce9

Please # to comment.