2015-04-21 87 views
0

我想編譯一個函數(「fun」)到LLVM IR並使用ParseIR函數創建一個模塊。該程序在ParseIR調用中發生段錯誤。我使用的是LLVM 3.5,代碼如下。LLVM ParseIR Segfault

#include <cstdio> 
#include <iostream> 
#include <sstream> 
#include <string> 

#include "llvm/ADT/StringRef.h" 
#include "llvm/Bitcode/ReaderWriter.h" 
#include "llvm/ExecutionEngine/ExecutionEngine.h" 
#include "llvm/ExecutionEngine/MCJIT.h" 
#include "llvm/IR/Instructions.h" 
#include "llvm/IR/LLVMContext.h" 
#include "llvm/IR/Module.h" 
#include "llvm/IRReader/IRReader.h" 
#include "llvm/Support/MemoryBuffer.h" 
#include "llvm/Support/raw_os_ostream.h" 

using std::cout; 
using std::endl; 
using std::ostringstream; 
using std::string; 

using llvm::getGlobalContext; 
using llvm::LLVMContext; 
using llvm::MemoryBuffer; 
using llvm::Module; 
using llvm::ParseIR; 
using llvm::SMDiagnostic; 
using llvm::StringRef; 

int main() { 
    string fun = "int fun(int x) {return x;}\n"; 

    string cmd = "echo '" + fun + "' |" 
       + " clang++ -cc1 -xc++ -O0 -std=c++1y -fno-use-cxa-atexit" 
       + " -I/usr/local/lib/clang/3.5.0/include/" 
       + " -I/usr/include/c++/4.9/" 
       + " -I/usr/include/x86_64-linux-gnu/c++/4.9/bits/" 
       + " -I/usr/include/x86_64-linux-gnu -I/usr/include/" 
       + " -I/usr/include/x86_64-linux-gnu/c++/4.9/" 
       + " -I/usr/lib/gcc/x86_64-linux-gnu/4.9/include/" 
       + " -I/usr/include/c++/4.9/backward/" 
       + " -I/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed/" 
       + " -stdlib=libstdc++ -S -emit-llvm" 
       + " -o /dev/stdout 2> /dev/stdout"; 

    FILE *file = popen(cmd.c_str(), "r"); 
    ostringstream llvm; 
    char line[1024]; 
    while (fgets(line, 1024, file)) 
     llvm << line; 
    pclose(file); 

    LLVMInitializeNativeTarget(); 
    LLVMInitializeNativeAsmPrinter(); 
    LLVMContext &ctx = getGlobalContext(); 
    SMDiagnostic *err; 
    StringRef ref = StringRef(llvm.str().c_str()); 
    MemoryBuffer *buff = MemoryBuffer::getMemBuffer(ref); 

    cout << "***** C++ *****\n" << fun << "\n" 
     << "***** LLVM *****\n" << llvm.str() << endl; 

    //segfault 
    Module *mod = ParseIR(buff, *err, ctx); 

    return 0; 
} 

我編譯和使用下面的命令運行上面的代碼:

g++ -std=c++14 fun.cpp -o fun `llvm-config --cxxflags --ldflags --libs --system-libs` 
./fun 
***** C++ ***** 
int fun(int x) {return x;} 

***** LLVM ***** 
; ModuleID = '-' 
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 
target triple = "x86_64-unknown-linux-gnu" 

; Function Attrs: nounwind 
define i32 @_Z3funi(i32 %x) #0 { 
    %1 = alloca i32, align 4 
    store i32 %x, i32* %1, align 4 
    %2 = load i32* %1, align 4 
    ret i32 %2 
} 

attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 

!llvm.ident = !{!0} 

!0 = metadata !{metadata !"clang version 3.5.1 (branches/release_35 225591)"} 

Segmentation fault (core dumped) 

回答

2

不要將您的SMDiagnostic*但取消對它的引用在調用ParseIR初始化。這就是爲什麼你的程序seg故障。請參閱代碼中的修改意見。

LLVMInitializeNativeTarget(); 
LLVMInitializeNativeAsmPrinter(); 
LLVMContext &ctx = getGlobalContext(); 
SMDiagnostic err; // create an SMDiagnostic instance 
MemoryBuffer* buff = MemoryBuffer::getMemBuffer(llvm.str()); 
cout << "***** C++ *****\n" << fun << "\n" 
    << "***** LLVM *****\n" << llvm.str() << endl; 

Module *mod = ParseIR(buff, err, ctx); // use err directly 
+1

這似乎並不成爲一個問題,但我也想警惕StringRef的'(llvm.str()。c_str())',因爲StringRef沒有自己的內容。 – zneak

+1

我編寫了一個答案,並用在我的程序中正常工作的方式替換了您的StringRef和MemoryBuffer初始化。你不必自己處理'StringRef's。只需將'std :: string'傳遞給'StringRef'參數即可。 –

+0

修正了這個問題,現在'ParseIR'正常工作,謝謝!然而,我遇到了下面的代碼,我嘗試添加下面的代碼: 'for(Module :: iterator i = mod-> begin(); i!= mod-> end(); + + i){...}' – agg212