Beispiel #1
0
/// forwardResume - Forward the 'resume' instruction to the caller's landing pad
/// block. When the landing pad block has only one predecessor, this is a simple
/// branch. When there is more than one predecessor, we need to split the
/// landing pad block after the landingpad instruction and jump to there.
void InvokeInliningInfo::forwardResume(ResumeInst *RI,
                               SmallPtrSet<LandingPadInst*, 16> &InlinedLPads) {
  BasicBlock *Dest = getInnerResumeDest();
  LandingPadInst *OuterLPad = getLandingPadInst();
  BasicBlock *Src = RI->getParent();

  BranchInst::Create(Dest, Src);

  // Update the PHIs in the destination. They were inserted in an order which
  // makes this work.
  addIncomingPHIValuesForInto(Src, Dest);

  InnerEHValuesPHI->addIncoming(RI->getOperand(0), Src);
  RI->eraseFromParent();

  // Append the clauses from the outer landing pad instruction into the inlined
  // landing pad instructions.
  for (SmallPtrSet<LandingPadInst*, 16>::iterator I = InlinedLPads.begin(),
         E = InlinedLPads.end(); I != E; ++I) {
    LandingPadInst *InlinedLPad = *I;
    for (unsigned OuterIdx = 0, OuterNum = OuterLPad->getNumClauses();
         OuterIdx != OuterNum; ++OuterIdx)
      InlinedLPad->addClause(OuterLPad->getClause(OuterIdx));
  }
}
Beispiel #2
0
/// HandleInlinedInvoke - If we inlined an invoke site, we need to convert calls
/// in the body of the inlined function into invokes.
///
/// II is the invoke instruction being inlined.  FirstNewBlock is the first
/// block of the inlined code (the last block is the end of the function),
/// and InlineCodeInfo is information about the code that got inlined.
static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
                                ClonedCodeInfo &InlinedCodeInfo) {
    BasicBlock *InvokeDest = II->getUnwindDest();

    Function *Caller = FirstNewBlock->getParent();

    // The inlined code is currently at the end of the function, scan from the
    // start of the inlined code to its end, checking for stuff we need to
    // rewrite.
    InvokeInliningInfo Invoke(II);

    // Get all of the inlined landing pad instructions.
    SmallPtrSet<LandingPadInst*, 16> InlinedLPads;
    for (Function::iterator I = FirstNewBlock, E = Caller->end(); I != E; ++I)
        if (InvokeInst *II = dyn_cast<InvokeInst>(I->getTerminator()))
            InlinedLPads.insert(II->getLandingPadInst());

    // Append the clauses from the outer landing pad instruction into the inlined
    // landing pad instructions.
    LandingPadInst *OuterLPad = Invoke.getLandingPadInst();
    for (SmallPtrSet<LandingPadInst*, 16>::iterator I = InlinedLPads.begin(),
            E = InlinedLPads.end(); I != E; ++I) {
        LandingPadInst *InlinedLPad = *I;
        unsigned OuterNum = OuterLPad->getNumClauses();
        InlinedLPad->reserveClauses(OuterNum);
        for (unsigned OuterIdx = 0; OuterIdx != OuterNum; ++OuterIdx)
            InlinedLPad->addClause(OuterLPad->getClause(OuterIdx));
        if (OuterLPad->isCleanup())
            InlinedLPad->setCleanup(true);
    }

    for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB) {
        if (InlinedCodeInfo.ContainsCalls)
            HandleCallsInBlockInlinedThroughInvoke(BB, Invoke);

        // Forward any resumes that are remaining here.
        if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator()))
            Invoke.forwardResume(RI, InlinedLPads);
    }

    // Now that everything is happy, we have one final detail.  The PHI nodes in
    // the exception destination block still have entries due to the original
    // invoke instruction. Eliminate these entries (which might even delete the
    // PHI node) now.
    InvokeDest->removePredecessor(II->getParent());
}
Beispiel #3
0
int main() {
    InitializeNativeTarget();
    LLVMContext& Context = getGlobalContext();
    Module *M = new Module("test C++ exception handling ", Context);


    StructType* MyStructType = StructType::create(Context, "struct.MyStruct");
    Type* MyStructFields[] = {
        Type::getInt32Ty(Context),
        Type::getInt32Ty(Context)
    };
    MyStructType->setBody(MyStructFields);

    GlobalValue* throwFunc = cast<GlobalValue>(M->getOrInsertFunction("throwMyStruct", Type::getVoidTy(Context), NULL));
    GlobalValue* MyStructTypeInfo = cast<GlobalValue>(M->getOrInsertGlobal("MyStructTypeInfo", Type::getInt8Ty(Context)));

    Function* gxx_personality = Function::Create(FunctionType::get(Type::getInt32Ty(Context), true), Function::ExternalLinkage, "__gxx_personality_v0", M);
    Function* begin_catch     = Function::Create(FunctionType::get(Type::getInt8PtrTy(Context), Type::getInt8PtrTy(Context), false), Function::ExternalLinkage, "__cxa_begin_catch", M);
    Function* end_catch       = Function::Create(FunctionType::get(Type::getVoidTy(Context), false), Function::ExternalLinkage, "__cxa_end_catch", M);

    Function* testExceptions = cast<Function>(M->getOrInsertFunction("testExceptions", Type::getInt32Ty(Context), NULL));

    BasicBlock* entryBB   = BasicBlock::Create(Context, "", testExceptions);
    BasicBlock* landPadBB = BasicBlock::Create(Context, "landPad", testExceptions);
    BasicBlock* noErrorBB = BasicBlock::Create(Context, "noError", testExceptions);


    IRBuilder<> builder(entryBB);

    Value* invokeThrow = builder.CreateInvoke(throwFunc, noErrorBB, landPadBB);

    builder.SetInsertPoint(noErrorBB);
    builder.CreateRet( builder.getInt32(666) ); // should never happen

    //writing landingpad! <<<<<<<

    builder.SetInsertPoint(landPadBB);

    Value* gxx_personality_i8 = builder.CreateBitCast(gxx_personality, Type::getInt8PtrTy(Context));
    Type* caughtType = StructType::get(builder.getInt8PtrTy(), builder.getInt32Ty(), NULL);

    LandingPadInst* caughtResult = builder.CreateLandingPad(caughtType, gxx_personality_i8, 1);

    // we can catch any C++ exception we want
    // but now we are catching MyStruct
    caughtResult->addClause(MyStructTypeInfo);

    //we are sure to catch MyStruct so no other checks are needed
    //if throwMyStruct() throws anything but MyStruct it won't pass to the current landingpad BB

    Value* thrownExctn  = builder.CreateExtractValue(caughtResult, 0);
    Value* thrownObject = builder.CreateCall(begin_catch, thrownExctn);
    Value* object       = builder.CreateBitCast(thrownObject, MyStructType->getPointerTo());
    Value* resultPtr    = builder.CreateStructGEP(object, 1);
    Value* result       = builder.CreateLoad(resultPtr);

    builder.CreateCall(end_catch);

    builder.CreateRet( result ); // << z.y

    TargetOptions Opts;
    Opts.JITExceptionHandling = true; // DO NOT FORGET THIS OPTION !!!!!!11


    ExecutionEngine* EE = EngineBuilder(M)
                        .setEngineKind(EngineKind::JIT)
                        .setTargetOptions(Opts)
                        .create();

    EE->addGlobalMapping(throwFunc, reinterpret_cast<void*>(&throwMyStruct));
    EE->addGlobalMapping(MyStructTypeInfo, MyStruct::getTypeInfo());

    verifyFunction(*testExceptions);
    outs() << *testExceptions;

    std::vector<GenericValue> noArgs;
    GenericValue gv = EE->runFunction(testExceptions, noArgs);

    outs() << "\ntestExceptions result: " << gv.IntVal << "\n";

    delete EE;
    llvm_shutdown();
    return 0;
}