llvm

2012-10-31 10 views
12

पर एक साधारण सफाई लैंडिंग पैड लिखना मैंने एक मूल कार्य Foo1 बनाया है जो किसी अन्य Bar2 को आह्वान के माध्यम से कॉल करता है।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?? 

मैं ईमानदारी से पता नहीं क्या मैं के लिए एक बुनियादी लैंडिंग पैड करने वाला कस्टम स्वच्छ invokes प्राप्त करने के लिए CreateLandingPad के मापदंडों के बीच डाल करने की जरूरत है: खोलना सफाई मूल ब्लॉक में पहली अनुदेश लैंडिंग पैड होना चाहिए मौजूदा Foo1 स्टैक ऑब्जेक्ट्स के लिए अप कोड। Bar2 सी ++ फ़ंक्शंस को कॉल करके फेंक सकता है जो खुद को फेंक देता है (या मौजूदा अपवाद को फिर से चलाता है)

उत्तर

6

मैं मानता हूं कि मेरे पास थोड़ा अनुभव है, लेकिन क्या आपने अपवाद डेमो कोड उदाहरण देखा है? ऐसा लगता है कि आप वास्तव में किस तरह के अनुक्रम को ढूंढने की उम्मीद कर रहे हैं।

मूल रूप से, आप व्यक्तित्व सेट करके प्रारंभ C++ के रूप में व्यवहार करने के लिए:

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

तब आप उस व्यक्तित्व के साथ landingpad बना सकते हैं और इसके प्रकार को परिभाषित: प्रकार की स्थापना

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

उदाहरण उदाहरण अपवाद डेमो दिलचस्प है, मुझे इसके बारे में पता नहीं था, धन्यवाद। कुछ जो मेरा ध्यान उठाता है वह यह है कि llvm :: फ़ंक्शन 'हमारी व्यक्तिगतता' के लिए बनाया गया है और लैंडिंग पैड में उपयोग किया जाता है, लेकिन मुझे इस फ़ंक्शन से वास्तविक 'हमारी व्यक्तिगतता' फ़ंक्शन के पते पर कहीं भी मैपिंग दिखाई नहीं दे रही है। मैपिंग खाली होने पर 'getFunction' डिफ़ॉल्ट रूप से प्रतीक रिज़ॉल्यूशन कर रहा है? मुझे उस 'फीचर' – lurscher

+0

@ लर्शर के लिए कोई दस्तावेज नहीं मिला जो मुझे नहीं पता; मुझे संदेह है कि इसकी परिभाषा (जो एक ही फाइल में दिखाई देती है) पर परिभाषित '_Unwind_Reason_Code' के साथ कुछ करने के लिए है, लेकिन मैं बस उस पूरे क्षेत्र से पर्याप्त परिचित नहीं हूं, मुझे डर है। – Oak

संबंधित मुद्दे