LLVM code generation with C++ API: How to handle OpenMP calls - llvm

I'm working on a compiler for a small language. Inside the compiler, I'm using the LLVM C++ API to generate llvm code, similar to the LLVM Kaleidoscope tutorial. So I'm using TheModule, TheContext, BasicBlocks,
and calls to Builder.Create...().
I can currently generate valid llvm code for arithmetic, control flow, and methods. However, I would also like my small language to support very simple OpenMP pragmas. For example,
#pragma omp parallel
{
print "Hello World"
}
I've tried writing a similar program in C++,
#include <iostream>
int main() {
#pragma omp parallel
{
std::cout << "Hi";
}
}
and generating llvm using clang++ -S -emit-llvm file.cpp -fopenmp. Along with the rest of the code, this generates the following lines which seem to implement the OpenMP functionality:
declare void #__kmpc_fork_call(%ident_t*, i32, void (i32*, i32*, ...)*, ...)
define internal void #.omp_outlined.(...)
From researching these statements, I found the Clang OpenMP API that contains calls like
OMPParallelDirective * OMPParallelDirective::Create(...)
I'm guessing this is what the Clang compiler uses to generate the statements above. However, it seems to be separate from the LLVM C++ API, as it doesn't reference TheContext, TheModule, etc...
So my question: Is there any way to leverage the Clang OpenMP API calls with my LLVM C++ API calls to generate the kmpc__fork_call and #.omp_outlined IR needed for parallel computation?
I did try decompiling the llvm generated from the C++ code back into LLVM C++ API code using llc -march=cpp file.bc ... but was unsuccessful.

The API you found operate on clang AST and are hardly usable outside clang. In fact, there are no OpenMP constructs at the LLVM IR level - everything is already lowered down to runtime calls, etc.
So, you'd really need to implement codegeneration for OpenMP by yourself emitting runtime calls as necessary (and per your language semantics).

Related

evaluating methods of libc++ in gdb when using clang

When compiling this
#include <vector>
#include <stdio.h>
int main()
{
std::vector<int> foo;
foo.push_back( 1 );
printf( "%zu\n", foo.size() );
}
with clang++ foo.cpp -stdlib=libc++ -g, when running a.out in gdb and trying to show the result of foo.size(), gdb says "Cannot evaluate function -- may be inlined".
Is there a way to avoid the compiler's inlining in debug mode? I could use libstdc++, but it is quite painful when it is needed to go inside the templates (many many subcalls plus indentation is sometimes space-based and sometimes tab-based).
I am running with Debian 9 (stretch) using libc++-dev v3.5 with clang 3.8 (tried with clang 5.0 too, same result) and gdb 7.12.
libstdc++ implements so called Python xmethods, see documentation:
Xmethods are additional methods or replacements for existing methods
of a C++ class. This feature is useful for those cases where a method
defined in C++ source code could be inlined or optimized out by the
compiler, making it unavailable to GDB. For such cases, one can define
an xmethod to serve as a replacement for the method defined in the C++
source code. GDB will then invoke the xmethod, instead of the C++
method, to evaluate expressions. One can also use xmethods when
debugging with core files. Moreover, when debugging live programs,
invoking an xmethod need not involve running the inferior (which can
potentially perturb its state). Hence, even if the C++ method is
available, it is better to use its replacement xmethod if one is
defined.
That's why you can call mock foo.size() even if the real foo.size() was inlined by compiler when using libstdc++. As far as I know there is no alike xmethod implementation for libc++.

llvm JIT add library to module

I am working on a JIT that uses LLVM. The language has a small run-time written in C++ which I compile down to LLVM IR using clang
clang++ runtime.cu --cuda-gpu-arch=sm_50 -c -emit-llvm
and then load the *.bc files, generate additional IR, and execute on the fly. The reason for the CUDA stuff is that I want to add some GPU acceleration to the runtime. However, this introduces CUDA specific external functions which gives errors such as:
LLVM ERROR: Program used external function 'cudaSetupArgument' which could not be resolved!
As discussed here, this is usually solved by including the appropriate libraries when compiling the program:
g++ main.c cmal.o -L/usr/local/cuda/lib64 -lcudart
However, I am not sure how to include libraries in JITed modules using LLVM. I found this question which suggested that is used to be possible to add libraries to modules in the JIT like this:
[your module]->addLibrary("m");
Unfortunately, this has been deprecated. Can anyone tell me the best way to do this now? Let me know if I need to provide more information!
Furthermore, I am not really sure if this is the best way to be incorporating GPU offloading into my JIT, so if anyone can point me to a better method then please do :)
Thanks!
EDIT: I am using LLVM 5.0 and the JIT engine I am using is from llvm/ExecutionEngine/ExecutionEngine.h, more specifically I create it like this:
EngineBuilder EB(std::move(module));
ExecutionEngine *EE = EB.create(targetMachine);
You need to teach your JIT engine about other symbols explicitly.
If they are in a dynamic library (dylib, so, dll) then you can just call
sys::DynamicLibrary::LoadLibraryPermanently("path_to_some.dylib")
with a path to the dynamic library.
If the symbols are in an object file or an archive, then it requires a bit more work: you would need to load them into memory and add to the ExecutionEngine using its APIs.
Here is an example for an object file:
std::string objectFileName("some_object_file.o");
ErrorOr<std::unique_ptr<MemoryBuffer>> buffer =
MemoryBuffer::getFile(objectFileName.c_str());
if (!buffer) {
// handle error
}
Expected<std::unique_ptr<ObjectFile>> objectOrError =
ObjectFile::createObjectFile(buffer.get()->getMemBufferRef());
if (!objectOrError) {
// handle error
}
std::unique_ptr<ObjectFile> objectFile(std::move(objectOrError.get()));
auto owningObject = OwningBinary<ObjectFile>(std::move(objectFile),
std::move(buffer.get()));
executionEngine.addObjectFile(std::move(owningObject));
For archives replace template types ObjectFile with Archive, and call
executionEngine.addArchive(std::move(owningArchive));
at the end.

compile c++ code with and without fopenmp flag

I have installed the C++ and Fortran compiler and tested the (C++) programs
(serial and parallel versions).
in Fortran when compiling a (parallelized) code without enabling the -openmp option should compile the code in (default) serial mode
but in C++ I get errors like
undefined reference to omp_get_thread_num
but in Fortran when you compile code without the -fopenmp flag it ignores any code which start with $!omp like
$!omp id = omp_get_thread_num()
Is there any option like that in C++?
You can protect your C/C++ code with the _OPENMP define. This way you can avoid introducing calls to the OpenMP runtime whenever your application is not linked against it.
For instance, you can have the following code
void foo (void)
{
#ifdef _OPENMP
printf ("I have been compiled with OpenMP support\n");
#else
printf ("I have been compiled without OpenMP support\n");
#endif
}

Apple LLVM 5.0 pragma optimize

What is the equivalent of GCC's #pragma GCC optimize("O0") or VS's #pragma optimize("", off) in Apple LLVM 5.0 compiler?
I need it to disable optimizations for just a section of code.
From a brief search it doesn't look like clang/llvm supports such a pragma at this time. If you don't want to turn off optimizations for an entire file I suggest factoring what you don't want optimized into a separate file and setting -O0 on it separately.
Actually there is now a way to do that by specifying an __attribute__ ((optnone)) to the function that wraps the code you don't want to be optimized.
For instance I'm using it to have a clear benchmark of an inline function
static void BM_notoptimizedfunction(benchmark::State& state) __attribute__ ((optnone)) {
// your code here won't be optimized by clang
}
And that's it !

How to generate machine code with llvm

I'm currently working on a compiler project using llvm. I have followed various tutorials to the point where I have a parser to create a syntax tree and then the tree is converted into an llvm Module using the provided IRBuilder.
My goal is to create an executable, and I am confused as what to do next. All the tutorials I've found just create the llvm module and print out the assembly using Module.dump(). Additionally, the only documentation I can find is for llvm developers, and not end users of the project.
If I want to generate machine code, what are the next steps? The llvm-mc project looks like it may do what I want, but I can't find any sort of documentation on it.
Perhaps I'm expecting llvm to do something that it doesn't. My expectation is that I can build a Module, then there would be an API that I can call with the Module and a target triple and an object file will be produced. I have found documentation and examples on producing a JIT, and I am not interested in that. I am looking for how to produce compiled binaries.
I am working on OS X, if that has any impact.
Use llc -filetype=obj to emit a linkable object file from your IR. You can look at the code of llc to see the LLVM API calls it makes to emit such code. At least for Mac OS X and Linux, the objects emitted in such a manner should be pretty good (i.e. this is not a "alpha quality" option by now).
LLVM does not contain a linker (yet!), however. So to actually link this object file into some executable or shared library, you will need to use the system linker. Note that even if you have an executable consisting of a single object file, the latter has to be linked anyway. Developers in the LLVM community are working on a real linker for LLVM, called lld. You can visit its page or search the mailing list archives to follow its progress.
As you can read on the llc guide, it is indeed intended to just generate the assembly, and then "The assembly language output can then be passed through a native assembler and linker to generate a native executable" - e.g. the gnu assembler (as) and linker (ld).
So the main answer here is to use native tools for assembling and linking.
However, there's experimental support for generating the native object directly from an IR file, via llc:
-filetype - Choose a file type (not all types are supported by all targets):
=asm - Emit an assembly ('.s') file
=obj - Emit a native object ('.o') file [experimental]
Or you can use llvm-mc to assemble it from the .s file:
-filetype - Choose an output file type:
=asm - Emit an assembly ('.s') file
=null - Don't emit anything (for timing purposes)
=obj - Emit a native object ('.o') file
I don't know about linkers, though.
In addition, I recommend checking out the tools/bugpoint/ToolRunner.h file, which exposes a wrapper combining llc and the platform's native C toolchain for generating machine code. From its header comment:
This file exposes an abstraction around a platform C compiler, used to compile C and assembly code.
Check out these functions in llvm-c/TargetMachine.h:
/** Emits an asm or object file for the given module to the filename. This
wraps several c++ only classes (among them a file stream). Returns any
error in ErrorMessage. Use LLVMDisposeMessage to dispose the message. */
LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
char *Filename, LLVMCodeGenFileType codegen, char **ErrorMessage);
/** Compile the LLVM IR stored in \p M and store the result in \p OutMemBuf. */
LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleRef M,
LLVMCodeGenFileType codegen, char** ErrorMessage, LLVMMemoryBufferRef *OutMemBuf);
To run the example BrainF program, compile it and run:
echo ,. > test.bf
./BrainF test.bf -o test.bc
llc -filetype=obj test.bc
gcc test.o -o a.out
./a.out
then type a single letter and press Enter. It should echo that letter back to you. (That's what ,. does.)
The above was tested with LLVM version 3.5.0.