2011-06-22 12 views
5

Programlama amacıyla C kaynağının bitlerini derlemek ve bağlamak için clang/llvm kullanıyorum. Ben llvm Linker çözülmemiş externals bir modülde bir hata olarak var olduğu gerçeğini bildirmek için görünmüyor buluyorum.Çözülmeyen dışsalları programlı olarak bulmak için llvm :: Linker'ı kullanma

Ben ettik Aşağıdaki kodu (uzunluk affet, ama bu gerçekten gerekli minimum):

biz hata veriyor sonuna yakın runFunction arayana kadar hiçbir hata her yerde meydana
int CompileAndLink() 
{ 
    llvm::InitializeNativeTarget(); 

    std::string code = "int UnresolvedFunction();\n" 
         "int main() { return UnresolvedFunction(); }"; 

    clang::DiagnosticOptions diagnosticOptions; 
    clang::TextDiagnosticPrinter tdp(llvm::outs(), diagnosticOptions);  
    llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs(new clang::DiagnosticIDs); 
    clang::Diagnostic diag(diagIDs, &tdp, false); 

    clang::FileSystemOptions fsOptions; 
    clang::FileManager fm(fsOptions); 

    clang::SourceManager sm(diag, fm); 
    clang::HeaderSearch hs(fm); 

    clang::TargetOptions targetOptions; 
    targetOptions.Triple = llvm::sys::getHostTriple(); 
    clang::TargetInfo* ti = clang::TargetInfo::CreateTargetInfo(diag, targetOptions);   

    clang::HeaderSearchOptions headerSearchOptions;   
    clang::LangOptions langOptions; 
    clang::ApplyHeaderSearchOptions(hs, headerSearchOptions, langOptions, ti->getTriple()); 

    clang::PreprocessorOptions ppo; 
    clang::Preprocessor pp(diag, langOptions, *ti, sm, hs); 

    clang::FrontendOptions frontendOptions; 
    clang::InitializePreprocessor(pp, ppo, headerSearchOptions, frontendOptions); 

    pp.getBuiltinInfo().InitializeBuiltins(pp.getIdentifierTable(), langOptions); 

    llvm::MemoryBuffer* sourceBuffer = llvm::MemoryBuffer::getMemBufferCopy(code); 
    sm.createMainFileIDForMemBuffer(sourceBuffer); 

    clang::Builtin::Context bic(*ti); 
    clang::ASTContext astc(langOptions, sm, *ti, 
          pp.getIdentifierTable(), 
          pp.getSelectorTable(), 
          bic, 
          0); 

    llvm::LLVMContext lc; 
    clang::CodeGenOptions codeGenOptions; 
    llvm::OwningPtr<clang::CodeGenerator> cg; 
    cg.reset(clang::CreateLLVMCodeGen(diag, "clang_test", codeGenOptions, lc)); 
    if(cg == NULL) { 
     printf("could not create CodeGenerator\n"); 
     return -1; 
    } 

    clang::ParseAST(pp, cg.get(), astc); 
    if(tdp.getNumErrors()) { 
     printf("error parsing AST\n"); 
     return -2; 
    } 

    llvm::Module* new_module = cg->ReleaseModule(); 
    if(!new_module) { 
     printf("error generating code\n"); 
     return -2; 
    } 

    llvm::Linker linker("clang_test", "clang_test", lc, llvm::Linker::Verbose ); 

    std::string error; 
    if(linker.LinkInModule(new_module, &error) || !error.empty()) { 
     printf("link error\n"); 
     return -3; 
    } 

    llvm::Module* composite_module = linker.getModule(); 
    if(composite_module == NULL) { 
     printf("link error\n"); 
     return -3; 
    } 

    llvm::ExecutionEngine *pEngine = llvm::ExecutionEngine::create(composite_module, 
                    false, 
                    &error); 
    if(!error.empty() || pEngine == NULL) { 
     printf("error creating ExecutionEngine\n"); 
     return -4; 
    } 

    llvm::Function* f = composite_module->getFunction("main"); 
    if(f == NULL) { 
     printf("couldn't find main function\n"); 
     return -5; 
    } 

    // This will abort with the message: 
    // LLVM ERROR: Program used external function 'UnresolvedFunction' which could not be resolved! 
    std::vector<llvm::GenericValue> params; 
    llvm::GenericValue result = pEngine->runFunction(f, params); 

    printf("function main returned %llu\n", result.IntVal.getZExtValue()); 

    return 0; 
} 

"LLVM HATA : Program çözümlenemeyen 'UnresolvedFunction' harici işlevini kullandı! " iptal edilmeden önce.

Bazı hatalarla başarısız olmak için LinkInModule veya getModule beklenen bekleniyor, ancak bu durum böyle değil. Benim sorum şu: Bir modülün çözülmemiş dışsal varlıklar olduğunu belirlemek için bir yol var mı? Kodun çalıştırılmaya çalışılmaya çalışılmaya çalışılmaması ve çökmemesi için mi? Oldukça uzun bir süredir bir süredir kaynağım var, ve aradığım şeyi bulamıyorum.

Mac OS X'te (x86_64) llvm/clang 2.9 kullanıyorum, eğer önemliyse.

Düzenleme: İstediğimi yapmak görünen LLVM kaynaklardan (LLVM-2.9/lib/Bağlayıcı/LinkArchives.cpp) içinde GetAllUndefinedSymbols denilen özel fonksiyon, buldum. Sanırım kaçırdığım bir şey için gerçek bir API var mıydı?

+0

GetAllUndefinedSybols'daki koddaki bir varyasyon olan @servn tarafından önerildiği gibi daha fazla veya daha az çalışıyorum. – zpasternack

cevap

2

IIRC, hiç kimse böyle bir API'yi istemedi, bu yüzden hiç mevcut değil. Neyse ki böyle bir API ile ne yapacağınızdan emin değilim ... önemsiz olmayan herhangi bir program, malloc gibi herhangi bir .bc dosyasında tanımlı olmayan sembolleri referans gösterecektir. Eğer gerçekten kontrol etmek isterseniz

, aşağıdaki gibi bir şey çalışması gerekir:

for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) 
    if (I->isDeclaration()) 
    UndefGlobals.insert(&*I); 

for (Module::global_iterator I = M->global_begin(), 
          E = M->global_end(); 
    I != E; ++I) 
    if (I->isDeclaration()) 
    UndefGlobals.insert(&*I); 
+0

Yapmaya çalıştığım şey, çözülmemiş dışsallıklar olup olmadığını iptal etmeden JIT'de bazı kodlar çalıştırmaktır. Kodunuz işe yaramaz (ancak, @Anton'un işaret ettiği gibi, bazı şeyler yanlış pozitiflere yol açan JIT tarafından sihirli bir şekilde çözülür). – zpasternack

2

LLVM bağlayıcı Modülleri bağlamak için kullanılır. Modülün dış beyanlara sahip olması için mükemmel bir şekilde geçerli olduğu düşünüldüğünde, hiçbir hata verilmemelidir. Bu nedenle, bu durumda hata yapmanıza gerek olup olmadığına karar vermeniz size bağlıdır (örneğin, bazı site dışı C kütüphanesi işlevlerine bazı dışsallıklar, JIT tarafından otomatik olarak çözülebilir)

Burada, servn'in kodu burada yapmanız gereken şeydir.

+0

Yeterince adil, teşekkürler! – zpasternack

+0

Anton, JIT'in otomatik olarak çözülmüş bağımlılıkların listesini nerede ve nasıl bulduklarını biliyor musunuz? Bakılabilecek çözülmemiş bir bağımlılık ekleyebileceğim bir yer var mı? – lurscher

+0

Sadece ana ikili dlopen'ing yoluyla. Daha fazla bilgi için DynamicLibrary sınıfına bakın –

İlgili konular