Help on Generating LLVM Module from C++ file using libClang

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Help on Generating LLVM Module from C++ file using libClang

Robinson, Paul via cfe-dev
Hi everyone,
  I want to generate LLVM Module from a C++ file using the LibClang C++ API. I am using clang 5.0.0 compiled from source. Currently, I am using EmitLLVMOnlyAction (as in clang-interpreter) to generate the LLVM Module.

  Unfortunately, I got an error "clang: Not enough positional command line arguments specified! Must specify at least 1 positional argument: See: clang -help" when I run ExecuteAction() on a CompilerInvocation object. I though this might be a missing argument problem so I printed out the driver::Command object which I used to create the CompilerInvocation object (I am using CompilerInvocation::CreateFromArgs() to create the object):

  "/home/cwz/llvm-root/build-5.0.0/bin/clang++" -cc1 -triple nvptx64-nvidia-cuda -emit-llvm-bc -emit-llvm-uselists -disable-free -main-file-name dummy.cpp -mrelocation-model static -mthread-model posix -mdisable-fp-elim -fmath-errno -no-integrated-as -dwarf-column-info -debugger-tuning=gdb -coverage-notes-file /home/cwz/piko-public/pikoc/samples/rasterPipelineFixPt/dummy.gcno -resource-dir /home/cwz/llvm-root/build-5.0.0/lib/clang/5.0.0 -I /usr/local/cuda/include -I ../../api/include -I ../../include -I basicTypes -I EasyBMP -I sceneParser -I util -I assimp/include -I bezmesh -D __PIKOC__ -D __PIKOC_DEVICE__ -I /home/cwz/piko-public/pikoc/samples/rasterPipelineFixPt -I /home/cwz/llvm-root/build-5.0.0/lib/clang/5.0.0/include -I /usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0 -I /usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/x86_64-linux-gnu/c++/5.4.0 -I /usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/backward -I /usr/local/include -I /include -I /usr/include -I /usr/include/x86_64-linux-gnu -fdeprecated-macro -fno-dwarf-directory-asm -fdebug-compilation-dir /home/cwz/piko-public/pikoc/samples/rasterPipelineFixPt -ferror-limit 19 -fmessage-length 204 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -o dummy.bc -x c++ dummy.cpp

  The dummy.cpp is the C++ file I want to compile to LLVM Module. The argument seems legit to me and I can compile dummy.cpp using clang from command line so I think the C++ file is good.

  Can anyone help me figure out why I am getting the not enogh positional argument error or point me to a better way to do this? Thanks in advance for your help. 

Best wishes,
Wenzhi Cui

The complete code snippet is here:



bool PikoBackend::createLLVMModule() {
  std
::string Path = "/home/cwz/llvm-root/build-5.0.0/bin/clang++";
  llvm
::errs() << "Path=" << Path << "\n";


  llvm
::IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  
TextDiagnosticPrinter *DiagClient =
    
new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);


  
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
  
DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);


  std
::string TripleStr = this->getTargetTriple() + "-" + "cuda";
  llvm
::Triple T(TripleStr);


  
Driver TheDriver(Path, T.str(), Diags);
  
TheDriver.setTitle("PikoPipe");
  
TheDriver.setCheckInputsExist(false);


  llvm
::SmallVector<const char *, 32> Args(pikocOptions.Argv,
    pikocOptions
.Argv + pikocOptions.Argc);
  
Args.push_back("-D__PIKOC__");
  
Args.push_back("-D__PIKOC_DEVICE__");
  
Args.push_back("-c");
  
Args.push_back("-emit-llvm");
  
Args.push_back("-xc++");


  std
::string include("-I");
  
auto include_cwd = include + pikocOptions.workingDir;
  
Args.push_back(include_cwd.c_str());
  
auto include_piko = include + pikocOptions.pikoIncludeDir;
  
Args.push_back(include_piko.c_str());
  
auto include_res = include + pikocOptions.clangResourceDir;
  
Args.push_back(include_res.c_str());
  
for(int i = 0; i < pikocOptions.includeDirs.size(); ++i) {
    
Args.push_back("-I");
    
Args.push_back(pikocOptions.includeDirs[i].c_str());
  
}


  std
::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args));
  
if (!C) {
    llvm
::errs() << "Compilation has problem building it\n";
    
return false;
  
}


  
const driver::JobList &Jobs = C->getJobs();
  
if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
    
SmallString<256> Msg;
    llvm
::raw_svector_ostream OS(Msg);
    
Jobs.Print(OS, "; ", true);
    
Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
    
return false;
  
}


  
const driver::Command &Cmd = cast<driver::Command>(*Jobs.begin());
  
if (llvm::StringRef(Cmd.getCreator().getName()) != "clang") {
    
Diags.Report(diag::err_fe_expected_clang_command);
    
return false;
  
}


  
// Initialize a compiler invocation object from the clang (-cc1) arguments.
  
const driver::ArgStringList &CCArgs = Cmd.getArguments();
  
Cmd.Print(llvm::errs(), "\n", false);
  std
::unique_ptr<CompilerInvocation> CI(new CompilerInvocation);
  
CompilerInvocation::CreateFromArgs(*CI,
                                     
const_cast<const char **>(CCArgs.data()),
                                     
const_cast<const char **>(CCArgs.data()) +
                                       
CCArgs.size() - 1,
                                     
Diags);


  
// Show the invocation, with -v.
  
if (CI->getHeaderSearchOpts().Verbose) {
    llvm
::errs() << "clang invocation:\n";
    
Jobs.Print(llvm::errs(), "\n", true);
    llvm
::errs() << "\n";
  
}


  
// FIXME: This is copied from cc1_main.cpp; simplify and eliminate.


  
// Create a compiler instance to handle the actual work.
  
CompilerInstance Clang;
  
Clang.setInvocation(std::move(CI));
  
Clang.getHeaderSearchOpts().ResourceDir = pikocOptions.clangResourceDir;


  
// Create the compilers actual diagnostics engine.
  
Clang.createDiagnostics();
  
if (!Clang.hasDiagnostics())
    
return false;


  llvm
::LLVMContext& ctx = GlobalContext;


  
// Create and execute the frontend to generate an LLVM bitcode module.
  llvm
::errs() << "Codegen...\n";
  std
::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&ctx));
  
if (!Clang.ExecuteAction(*Act)) {
    llvm
::errs() << "Parsing erros...\n";
    
return false;
  
}


  
if(Clang.getDiagnostics().hasErrorOccurred()) {
    llvm
::errs() << "Parsing erros in diagnostics...\n";
    
return false;
  
}


  
this->module = Act->takeModule().get();


  
return true;
}

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev