[cfe-dev] Replacing the main input file with a buffer

Yaron Keren yaron.keren at gmail.com
Wed Jan 22 11:55:37 PST 2014


cling uses this approach so it can add more source lines to the input file
as they come in from the user.

You may have an easier solution:

1 Use SourceManager.getFileManager().getVirtualFile() to create a virtual
source file.
2 Allocate a MemoryBuffer with your sources.
3 Use overrideFileContents to replace the file contents with the
MemoryBuffer.
4 Pass the virtual file file name to clang::CompilerInstance.

Yaron



2014/1/22 Graham Lee <graham at iamleeg.com>

> Hi all,
>
>
> I’ve got an application that uses the clang frontend to generate a bit
> code module that’s run by LLVM’s JIT. The current way it works is to take
> the user-supplied source, write it to a temporary file and construct a
> clang invocation to compile that source file, based on the code in clang’s
> examples/clang-interpreter/. That works, but I want to use a memory buffer
> instead of the main file to avoid making all these temporary files.
>
>
> What I have tried:
>
> - initialising the source manager with my buffer:
>
>   // the args used by the driver have “-“ as the input file
>
>   // and ‘Clang’ is a clang::CompilerInstance
>
>   Clang.setInvocation(CI.take());
>
>   Clang.createDiagnostics();
>
>   if (!Clang.hasDiagnostics())
>
>   {
>
>       if (error)
>
>       {
>
>           *error = [self
> compilerErrorWithCode:IKBCompilerErrorCouldNotReportUnderlyingErrors
> compilerOutput:diagnostic_output];
>
>       }
>
>       return nil;
>
>   }
>
>
>   Clang.createFileManager();
>
>   Clang.createSourceManager(Clang.getFileManager());
>
>   llvm::StringRef sourceString([source UTF8String]);
>
>   llvm::MemoryBuffer* mainFile =
> llvm::MemoryBuffer::getMemBuffer(sourceString);
>
>   FrontendInputFile inputFile(mainFile, IK_ObjC);
>
>   Clang.InitializeSourceManager(inputFile);
>
>
> - creating a main file ID with the buffer. I used the approach taken by
> cling here:
> https://github.com/cxx-hep/root-cern/blob/be3c582075364538f14b65ba5f528f730ef8f2ba/interpreter/cling/lib/Interpreter/CIFactory.cpp#L239-L263
>
> - following the other branch in cling’s example above, I tried setting the
> main file’s content buffer to be my buffer.
>
>
> In each case, I try to execute an EmitLLVMOnlyAction(). This waits without
> completing, and I find that the application has paused in ::read(), waiting
> for data from stdin. Indeed if I launch my application from the terminal
> and press Ctrl-D when I get to that point, this happens:
>
>
> Assertion failed: ((!RequiresNullTerminator || BufEnd[0] == 0) && "Buffer
> is not null terminated!"), function init, file
> /Users/leeg/Documents/OtherProjects/llvm/lib/Support/MemoryBuffer.cpp, line
> 57.
>
>
> So it seems that none of the three things I have tried above has actually
> convinced the compiler instance that it should read the main file from my
> buffer, instead of stdin. Clearly I’ve missed some step in the problem, but
> can someone please tell me what that step is?
>
>
> For more context, the full application is at
> https://bitbucket.org/iamleeg/ikbclassbrowser and the (current, working)
> way to invoke clang is at
> https://bitbucket.org/iamleeg/ikbclassbrowser/src/2ea5643705fdeccd3c2bea08c516e3289f9a9fd8/ClassBrowser/Code%20Execution/IKBClangCompiler.mm?at=master#cl-80
> .
>
>
> Thanks,
>
> Graham.
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140122/109d37f5/attachment.html>


More information about the cfe-dev mailing list