2012-10-31 1 views
12

나는 invoke를 통해 Bar2을 또 하나 호출하는 기본 기능 Foo1을 만들었습니다.llvm에 간단한 정리 착륙 패드 작성

void bar2() 
{ 
    throw; 
} 
llvm::Function* Bar2Fn = llvm::Function::Create(voidSig , &bar2); 
engine->addGlobalMapping(Bar2Fn, (void*)&bar2); 
llvm::InvokeInst* inv = builder.CreateInvoke(Bar2Fn , continueBlock, unwindBlock, llvmArgValues , "invoke"); 
builder.CreateBr(continueBlock); 
builder.SetInsertPoint(unwindBlock); 
llvm::LandingPadInst* landPadInst = builder.CreateLandingPad(...); 
//add some cleanup code? where?? 

내가 정의 청소를 호출하는 기본 랜딩 패드를 얻기 위해 CreateLandingPad의 매개 변수 사이에 둘 필요가 무엇인지 솔직히 아무 생각이 : 언 와인드 정리 기본 블록의 첫 번째 명령은 랜딩 패드 있어야합니다 현재 Foo1 스택 개체에 대한 최대 코드입니다. Bar2 자체 던져 던지거나 (또는 ​​기존 예외를 rethrow) C++ 함수를 호출하여 던질 수도 있습니다

답변

6

나는 약간의 경험이 있지만 여기에 예외 데모 코드 예제를 보았습니까? 그것은 당신이 찾고자하는 서열의 종류를 정확하게 포함하고있는 것처럼 보입니다.

llvm::Function *personality = module.getFunction("__gxx_personality_v0"); 

당신은 그 성격과 landingpad를 작성하고 해당 유형 정의 :

기본적으로, 당신은 C++에서와 같이 행동하는 성격을 설정하여 시작 유형을 설정

llvm::LandingPadInst *caughtResult = 
    builder.CreateLandingPad(ourCaughtResultType, 
          personality, 
          numExceptionsToCatch, 
          "landingPad"); 

을 잡는 방법 :

for (unsigned i = 0; i < numExceptionsToCatch; ++i) { 
    // Set up type infos to be caught 
    caughtResult->addClause(module.getGlobalVariable(
          ourTypeInfoNames[exceptionTypesToCatch[i]])); 
} 

그리고 정리 작업 처리기 :

caughtResult->setCleanup(true); 

이것은 믿습니다. 지금 당신은 예외 자체를 얻을 수 있습니다 :

llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0); 

이 코드 세그먼트를 가져온 ExceptionDemo.cpp 파일, 풀러 순서를 포함을; 귀하의 정리 코드를 - - 구체적으로는 특정 블록에 잡힌 예외 가지의 유형 루트를 확인하는 방법을 보여줍니다 뭔가 일치 할 때 :

llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1); 

// FIXME: Redundant storage which, beyond utilizing value of 
//  caughtResultStore for unwindException storage, may be alleviated 
//  altogether with a block rearrangement 
builder.CreateStore(caughtResult, caughtResultStorage); 
builder.CreateStore(unwindException, exceptionStorage); 
builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag); 

// Retrieve exception_class member from thrown exception 
// (_Unwind_Exception instance). This member tells us whether or not 
// the exception is foreign. 
llvm::Value *unwindExceptionClass = 
    builder.CreateLoad(builder.CreateStructGEP(
      builder.CreatePointerCast(unwindException, 
            ourUnwindExceptionType->getPointerTo()), 
              0)); 

// Branch to the externalExceptionBlock if the exception is foreign or 
// to a catch router if not. Either way the finally block will be run. 
builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass, 
          llvm::ConstantInt::get(builder.getInt64Ty(), 
               ourBaseExceptionClass)), 
        exceptionRouteBlock, 
        externalExceptionBlock); 

마지막으로, 추가 예를 들어, 설명과 함께들을 수 있습니다 on the blog post that introduced the new exception handling mechanism .

+0

예를 들어 ExceptionDemo가 흥미 롭습니다. 감사합니다. 감사합니다. 필자의 주목을 끄는 점은 llvm :: Function이'ourPersonality'를 위해 생성되고 랜딩 패드에서 사용된다는 것입니다. 그러나이 함수에서 실제'ourPersonality' 함수의 주소로 매핑하는 것을 볼 수는 없습니다. 매핑이 비어 있다면'getFunction'은 기본적으로 심볼 해석을하고 있습니까? 그 '기능'에 대한 문서를 찾을 수 없었습니다 – lurscher

+0

@lurscher 저는 잘 모릅니다. 나는 그것이 (동일한 파일에 나타나는) 정의에 정의 된'_Unwind_Reason_Code'와 관련이 있다고 의심하지만, 나는 그 전체 영역에 익숙하지 않다. 나는 두렵다. – Oak