[cfe-dev] Help on Generating LLVM Module from C++ file using libClang

WENZHI CUI via cfe-dev cfe-dev at lists.llvm.org
Mon Nov 20 08:49:31 PST 2017


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;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20171120/7d94e7aa/attachment.html>


More information about the cfe-dev mailing list