Pytanie pisanie prostego lądowania na lvvm


Stworzyłem podstawową funkcję Foo1 który wzywa inny Bar2 przez wywołanie. Pierwsza instrukcja w podstawowym bloku odprężania musi być lądowiskiem:

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??

Szczerze mówiąc nie mam pojęcia, co muszę umieścić między parametrami CreateLandingPad w celu uzyskania podstawowego lądowiska, który wywołuje niestandardowy kod oczyszczania dla prądu Foo1 stos obiektów. Bar2 może rzucić, wywołując funkcje c ++, które same rzucają (lub wyrzucają istniejący wyjątek)


12
2017-10-31 19:58


pochodzenie




Odpowiedzi:


Przyznaję, że mam tu niewielkie doświadczenie, ale czy widziałeś przykład kodu demo wyjątku? Wygląda na to, że zawiera dokładnie ten rodzaj sekwencji, którą masz nadzieję znaleźć.

Zasadniczo zaczynasz od ustawienia osobowości, aby zachowywała się jak w C ++:

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

Następnie utworzysz lądownik z tą osobowością i zdefiniujesz jego typ:

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

Konfigurowanie typów do przechwytywania:

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

I sygnalizowanie, że jest to program czyszczący:

caughtResult->setCleanup(true);

Myślę, że to jest to; teraz możesz sam uzyskać wyjątek:

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

The ExceptionDemo.cpp plik, z którego pochodzą te segmenty kodu, zawiera pełniejszą sekwencję; w szczególności pokazuje, jak sprawdzić typ root wychwyconego wyjątku i rozgałęzienia w konkretnym bloku - twój kod oczyszczający - kiedy coś pasuje:

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);

Na koniec dostępny jest dodatkowy przykład wraz z objaśnieniami na blogu, który wprowadził nowy mechanizm obsługi wyjątków.


6
2017-11-06 15:00



ten przykład ExceptionDemo jest interesujący, nie wiedziałem o tym, dzięki. Coś, co zwróci moją uwagę, jest to, że stworzono funkcję llvm :: Function ourPersonality i używane w lądowisku, ale nie widzę nigdzie mapowania z tej funkcji na adres rzeczywistego ourPersonality funkcjonować. Jest getFunction domyślnie robi rozdzielczość symbolu, jeśli mapowanie jest puste ?. Nie mogłem znaleźć żadnej dokumentacji dla tej "funkcji" - lurscher
@lurscher Nie wiem; Podejrzewam, że ma to coś wspólnego z _Unwind_Reason_Code zdefiniowany w jego definicji (która pojawia się w tym samym pliku), ale nie jestem po prostu znajomy wystarczająco z tego całego obszaru, obawiam się. - Oak