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

181 views
Skip to first unread message

cwz9...@gmail.com

unread,
Nov 19, 2017, 7:54:53 PM11/19/17
to Clang maintainers
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;
}

Hans Wennborg

unread,
Nov 20, 2017, 11:44:32 AM11/20/17
to cwz9...@gmail.com, Clang maintainers
Hi Wenzhi,

This list is about the use of Clang in the Chromium project. I think a
better list to ask your question would be cfe-dev:
https://lists.llvm.org/mailman/listinfo/cfe-dev

Thanks,
Hans

WENZHI CUI

unread,
Nov 20, 2017, 11:47:00 AM11/20/17
to Clang maintainers, cwz9...@gmail.com
Sorry about the confusion and I will post it to cfe-dev. I am sorry about this mistake.
Reply all
Reply to author
Forward
0 new messages