2012-10-31 6 views
12

Ich habe eine Basisfunktion Foo1 erstellt, die eine andere Bar2 durch Aufruf aufruft. Der erste Befehl in dem Abroll Bereinigungsbasisblock muss der Landeplatz sein:schreiben eine einfache Reinigung Landeplatz auf 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?? 

Ich habe ehrlich gesagt keine Ahnung, was ich zwischen den Parametern von CreateLandingPad in Ordnung bringen muß, um einen grundlegenden Landeplatz zu erhalten, die ein benutzerdefinierten sauber ruft Up-Code für die aktuellen Foo1 Stapelobjekte. Bar2 könnte durch Aufruf von C++ Funktionen werfen, die selbst werfen (oder eine vorhandene Ausnahme erneut auslösen)

Antwort

6

Ich gebe zu, ich habe wenig Erfahrung hier, aber haben Sie die Ausnahme Demo-Code Beispiel gesehen? Es scheint genau die Art von Sequenz zu enthalten, die Sie zu finden hoffen.

Grundsätzlich starten Sie durch die Persönlichkeit der Einrichtung wie in C verhalten ++:

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

Sie dann die landingpad schaffen mit dieser Persönlichkeit und seine Art definieren:

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

die Typen einrichten zu fangen:

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

Und Signalisierung ist es eine Aufräumbehandlung:

caughtResult->setCleanup(true); 

Das ist es, glaube ich; jetzt können Sie die Ausnahme selbst erhalten:

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

Die ExceptionDemo.cpp Datei, aus denen diese Codesegmente genommen werden, enthält eine vollständigere Sequenz; Insbesondere zeigt es, wie die Art Wurzel der abgefangene Ausnahme und verzweigen sich in einem bestimmten Block überprüfen - Ihre Bereinigungscode - wenn es etwas übereinstimmt:

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

schließlich ein weiteres Beispiel, zusammen mit Erläuterungen zur Verfügung on the blog post that introduced the new exception handling mechanism .

+0

das Beispiel ExceptionDemo ist interessant, ich wusste es nicht, danke. Etwas, das meine Aufmerksamkeit auf sich zieht, ist, dass die llvm :: Function für "unserePersonalität" erstellt und im Landing Pad verwendet wird, aber ich sehe nirgendwo eine Zuordnung von dieser Funktion zur Adresse der tatsächlichen 'ourPersonality' Funktion. Ist 'getFunction' standardmäßig die Symbolauflösung, wenn das Mapping leer ist? Ich konnte keine Dokumentation für dieses "Feature" finden – lurscher

+0

@lurscher Ich weiß es nicht; Ich vermute, dass es etwas mit dem '_Unwind_Reason_Code' zu ​​tun hat, der in seiner Definition definiert ist (der in der gleichen Datei erscheint), aber ich bin einfach nicht vertraut genug mit diesem ganzen Bereich, fürchte ich. – Oak