olarak adlandırılan temizleme JIT llvm kodu içinde bir özel durum işleyici oluşturmaya çalışıyorum. exception handling in LLVM ile ilgili mevcut belgeler şu anda çok el sıkıntısıdır, bu yüzden bir çalışma örneği elde etmek için http://llvm.org/demo'dan aldığım parçacıkların çoğunu yeniden kullanmaya çalışıyorum, ancak bunların llvm ile güncel olup olmadığından emin değilim. 2.9 (kullanıyorum sürümü). Modül: dump(); i işlevi gerçekleştirmek için çalışırkenllvm istisnaları; yakalama işleyici, temizleme değil
; ModuleID = 'testModule'
declare i32 @myfunc()
define i32 @test_function_that_invokes_another() {
entryBlock:
%0 = alloca i8*
%1 = alloca i32
%someName = invoke i32 @myfunc()
to label %exitBlock unwind label %unwindBlock
exitBlock: ; preds = %entryBlock
ret i32 1
unwindBlock: ; preds = %entryBlock
%2 = call i8* @llvm.eh.exception()
store i8* %2, i8** %0
%3 = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* %2, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null)
store i32 1, i32* %1
%4 = load i8** %0
%5 = call i32 (...)* @__cxa_begin_catch(i8* %4) nounwind
%cleanup_call = call i32 @myCleanup()
%6 = call i32 (...)* @__cxa_end_catch()
ret i32 1
}
declare i32 @__gxx_personality_v0(...)
declare i32 @__cxa_begin_catch(...)
declare i32 @__cxa_end_catch(...)
declare i8* @llvm.eh.exception() nounwind readonly
declare i32 @llvm.eh.selector(i8*, i8*, ...) nounwind
declare i32 @myCleanup()
ve bu olur:
inside JIT calling C/C++ call
terminate called after throwing an instance of 'int'
Aborted
bu atar işlevi atar, çağrılan olduğunu gösterir, ama temizleme çağrısında karaya olmadı.
const inline llvm::FunctionType* getTestFunctionSignature(llvm::LLVMContext& context) {
return llvm::TypeBuilder< unsigned int(), false > ::get(context);
}
llvm::Function* createFunctionThatInvokesAnother(llvm::LLVMContext& ctx, llvm::Module* mod , llvm::Function* another) {
llvm::Function* result = llvm::Function::Create(getTestFunctionSignature(ctx),
llvm::GlobalValue::ExternalLinkage,
"test_function_that_invokes_another",
mod);
llvm::BasicBlock* entry_block = llvm::BasicBlock::Create(ctx, "entryBlock", result);
llvm::BasicBlock* exit_block = llvm::BasicBlock::Create(ctx, "exitBlock", result);
llvm::BasicBlock* unwind_block = llvm::BasicBlock::Create(ctx, "unwindBlock", result);
llvm::IRBuilder<> builder(entry_block);
llvm::ConstantInt* ci = llvm::ConstantInt::get(mod->getContext() , llvm::APInt(32 , llvm::StringRef("1"), 10));
llvm::PointerType* pty3 = llvm::PointerType::get(llvm::IntegerType::get(mod->getContext(), 8), 0);
llvm::AllocaInst* ptr_24 = new llvm::AllocaInst(pty3, "", entry_block);
llvm::AllocaInst* ptr_25 = new llvm::AllocaInst(llvm::IntegerType::get(mod->getContext(), 32), "", entry_block);
llvm::Twine name("someName");
builder.CreateInvoke(another , exit_block , unwind_block , "someName");
builder.SetInsertPoint(exit_block);
builder.CreateRet(ci);
builder.SetInsertPoint(unwind_block);
llvm::Function* func___gxx_personality_v0 = func__gxx_personality_v0(mod);
llvm::Function* func___cxa_begin_catch = func__cxa_begin_catch(mod);
llvm::Function* func___cxa_end_catch = func__cxa_end_catch(mod);
llvm::Function* func_eh_ex = func_llvm_eh_exception(mod);
llvm::Function* func_eh_sel = func__llvm_eh_selector(mod);
llvm::Constant* const_ptr_17 = llvm::ConstantExpr::getCast(llvm::Instruction::BitCast, func___gxx_personality_v0, pty3);
llvm::ConstantPointerNull* const_ptr_18 = llvm::ConstantPointerNull::get(pty3);
llvm::CallInst* get_ex = llvm::CallInst::Create(func_eh_ex, "", unwind_block);
get_ex->setCallingConv(llvm::CallingConv::C);
get_ex->setTailCall(false);
new llvm::StoreInst(get_ex, ptr_24, false, unwind_block);
std::vector<llvm::Value*> int32_37_params;
int32_37_params.push_back(get_ex);
int32_37_params.push_back(const_ptr_17);
int32_37_params.push_back(const_ptr_18);
llvm::CallInst* eh_sel = llvm::CallInst::Create(func_eh_sel, int32_37_params.begin(), int32_37_params.end(), "", unwind_block);
eh_sel->setCallingConv(llvm::CallingConv::C);
eh_sel->setTailCall(false);
new llvm::StoreInst(ci, ptr_25, false, unwind_block);
llvm::LoadInst* ptr_29 = new llvm::LoadInst(ptr_24, "", false, unwind_block);
llvm::CallInst* ptr_30 = llvm::CallInst::Create(func___cxa_begin_catch, ptr_29, "", unwind_block);
ptr_30->setCallingConv(llvm::CallingConv::C);
ptr_30->setTailCall(false);
llvm::AttrListPtr ptr_30_PAL;
{
llvm::SmallVector<llvm::AttributeWithIndex, 4 > Attrs;
llvm::AttributeWithIndex PAWI;
PAWI.Index = 4294967295U;
PAWI.Attrs = 0 | llvm::Attribute::NoUnwind;
Attrs.push_back(PAWI);
ptr_30_PAL = llvm::AttrListPtr::get(Attrs.begin(), Attrs.end());
}
ptr_30->setAttributes(ptr_30_PAL);
llvm::Function* cleanup = call_myCleanup(mod);
builder.CreateCall(cleanup , "cleanup_call");
llvm::CallInst* end_catch = llvm::CallInst::Create(func___cxa_end_catch, "", unwind_block);
builder.CreateRet(ci);
//createCatchHandler(mod , unwind_block);
return result;
}
Bu olağan bir iş gibi çağrılan:
çağırır ve fonksiyon (deneme) bir atılan istisnadır yakalamak için (benim temizleme çağrısı 'JIT çağıran C/C++ Temizleme içeride' demeliydim) :
atar benim işlevitestMain() {
llvm::LLVMContext ctx;
llvm::InitializeNativeTarget();
llvm::StringRef idRef("testModule");
llvm::Module* module = new llvm::Module(idRef, ctx);
std::string jitErrorString;
llvm::ExecutionEngine* execEngine = executionEngine(module , jitErrorString);
llvm::FunctionPassManager* OurFPM = new llvm::FunctionPassManager(module);
llvm::Function *thr = call_my_func_that_throws(module);
llvm::Function* result = createFunctionThatInvokesAnother(ctx, module ,thr);
std::string errorInfo;
llvm::verifyModule(* module, llvm::PrintMessageAction, & errorInfo);
module->dump();
void *fptr = execEngine->getPointerToFunction(result);
unsigned int (*fp)() = (unsigned int (*)())fptr;
try {
unsigned int value = fp();
} catch (...) {
std::cout << " handled a throw from JIT function" << std::endl;
}
}
olduğu:
int myfunc() {
std::cout << " inside JIT calling C/C++ call" << std::endl;
throw 0;
};
llvm::Function* call_my_func_that_throws (llvm::Module* mod) {
std::vector< const llvm::Type* > FuncTy_ex_args;
llvm::FunctionType* FuncTy_ex = llvm::FunctionType::get(llvm::IntegerType::get(mod->getContext() , 32) , FuncTy_ex_args , false);
llvm::Function* result = llvm::Function::Create(FuncTy_ex, llvm::GlobalValue::ExternalLinkage, "myfunc", mod);
result->setCallingConv(llvm::CallingConv::C);
llvm::AttrListPtr PAL;
result->setAttributes(PAL);
llvm::sys::DynamicLibrary::AddSymbol("myfunc" , (void*) &myfunc);
return result;
}
ve benim temizleme fonksiyon benzer şekilde tanımlanır: bu değişiklikler gerçek çevirmek nasıl
int myCleanup() {
std::cout << " inside JIT calling C/C++ Cleanup" << std::endl;
return 18;
};
llvm::Function* call_myCleanup (llvm::Module* mod) {
std::vector< const llvm::Type* > FuncTy_ex_args;
llvm::FunctionType* FuncTy_ex = llvm::FunctionType::get(llvm::IntegerType::get(mod->getContext() , 32) , FuncTy_ex_args , false);
llvm::Function* result = llvm::Function::Create(FuncTy_ex, llvm::GlobalValue::ExternalLinkage, "myCleanup", mod);
result->setCallingConv(llvm::CallingConv::C);
llvm::AttrListPtr PAL;
result->setAttributes(PAL);
llvm::sys::DynamicLibrary::AddSymbol("myCleanup" , (void*) &myCleanup);
return result;
}
Ben de LLVM son istisna işleme değişikliklerle ilgili
this document okudum, ama belli değil, sen
mükemmel, yeni yaklaşımı kullanarak bir örneğe işaret edebilir misiniz, bu yazıyı okuyorum: http://lists.cs.uiuc.edu/pipermail/llvmdev/2011-July/041768.html ama ben ' Ne yapmam gerektiğinden emin değilim – lurscher
eh docs yeniden yazılmıştır, bu yüzden doğru olmalıdır. Başka bir seçenek nasıl görünmesi gerektiğine dair fikir edinmek için clang çıkışına bakmaktır. – echristo