How to easily add declarations to the LLVM module? - llvm

I'm writing my own language in LLVM and I'm using external C functions from std and custom. I'm now adding declarations using C++ classes for LLVM IR. Like this:
void register_malloc(llvm::Module *module) {
std::vector<llvm::Type*> arg_types;
arg_types.push_back(Type::getInt32Ty(getGlobalContext()));
FunctionType* type = FunctionType::get(
Type::getInt8PtrTy(getGlobalContext()), arg_types, false);
Function *func = Function::Create(
type, llvm::Function::ExternalLinkage,
llvm::Twine("malloc"),
module
);
func->setCallingConv(llvm::CallingConv::C);
}
void register_printf(llvm::Module *module) {
std::vector<llvm::Type*> printf_arg_types;
printf_arg_types.push_back(llvm::Type::getInt8PtrTy(getGlobalContext()));
llvm::FunctionType* printf_type =
llvm::FunctionType::get(
llvm::Type::getInt32Ty(getGlobalContext()), printf_arg_types, true);
llvm::Function *func = llvm::Function::Create(
printf_type, llvm::Function::ExternalLinkage,
llvm::Twine("printf"),
module
);
func->setCallingConv(llvm::CallingConv::C);
}
I'm gonna define tens of external functions, is there some easy way to define them, and how?
I think about "including" C header(or LLVM IR file .ll) to the module. But I couldn't find any example how to do this...

Create an empty C source and include every header you need, then compile it to LLVM IR with clang -S -emit-llvm. This source would contain declarations for every function from headers. Now use llc -march=cpp out.ll and it will produce C++ source that calls LLVM API to generate given IR. You can copy-paste this code into your program.
Make sure you have cpp backend enabled during LLVM build.

Related

Compiling Rust that calls C++ to WASM

I've found this How do I use a C library in a Rust library compiled to WebAssembly?, but this relies on wasm-merge, which has been discontinued. My problem is the following, I have some C++ code that I would like to call from Rust in order to have the option to compile the resulting package either to native code for use in mobile apps or to Webassembly for use in Node.js. At the moment, I have the following setup:
libTest.cpp
extern "C"{
int test_function(int i){
return i;
}
}
lib.rs
use wasm_bindgen::prelude::*;
#[link(name = "Test")]
extern "C"{
pub fn test_function(i: i32) -> i32 ;
}
#[wasm_bindgen]
pub fn test_function_js(i : i32) -> i32{
let res = unsafe{test_function(i)};
res
}
build.rs
fn main() {
cc::Build::new()
.cpp(true)
.file("libTest.cpp")
.compile("libTest.a");
}
This compiles and works when compiling to native code using a simple cargo build, but does not work for building to wasm, for which I'm doing cargo build --target wasm32-unknown-unknown. There I get the two errors
= note: rust-lld: error: /[path to my project]/target/wasm32-unknown-unknown/debug/build/rustCpp-cc5e129d4ee03598/out/libTest.a: archive has no index; run ranlib to add one
rust-lld: error: unable to find library -lstdc++
Is this the right way to go about this and if yes, how do I resolve the above error? If not, how do I best go about calling C++ from Rust and compiling it to wasm?
(This is not really a full answer, but too long for a comment.)
I can compile your example with
cc::Build::new()
.archiver("llvm-ar") // Takes care of "archive has no index" - emar might be an alternative
.cpp_link_stdlib(None) // Takes care of "unable to find library -lstdc++"
… // rest of your flags
but I'm not sure whether the resulting binary is useful to you. Especially, it contains WASI imports when compiled in debug mode, and you'll probably get linker errors if you start using any interesting functions (e.g. sin).
You could in theory give the C++ compiler a full stdlib to work with through .flag("--sysroot=/usr/share/wasi-sysroot/") (if you have wasi-sdk or wasi-libc++ installed), but
I'm unsure how to best account for differences of where this folder is usually installed (maybe like this)
I think you have to also pass this flag at link time, but I don't know how (it seems to work without, though)
that would target wasi, and may not be useful for whatever bindgen-based environment you have in mind.

How to linking a external function from a .h file (header file) for LLVM getOrInsertFunction in a LLVM pass

let consider a header file named foo.h
#ifndef __FOO_H__
#define __FOO_H__
#include<stdio.h>
void display(){
printf("Hello");
}
#endif
and a simple program named simple.c
#include<stdio.h>
void main(){
//instrument display() at these point to print "Hello".
printf(" World\n");
}
so how to coded in instrumentation.cpp to link that foo.h file and get that display() function for doing
getOrInsertFunction("display", false);.
What does the input to your instrumentation pass look like? You will need to be comfortable thinking in terms of LLVM IR.
Take that simple.c and turn it into LLVM IR and look at it. What do you want the result to look like after your instrumentation? Does this instrumentation add a declaration of "display" and a call to it? That would imply that "display()" function is in a separate library which gets linked in. Or do you want to compile display() down to LLVM IR and have your instrumentation pass add the whole thing to the module being instrumented? Are you OK with placing a call to display() or do you want to then inline that call?
clang -S -emit-llvm file.c will produce LLVM IR as text.
Given an llvm::IRBuilder Builder, Builder.CreateCall can be used to add a function call.
Once you have two modules in memory, you can add another module into the current module with llvm::linkModules, or you may want to use CloneModuleInto.

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.

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

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).

Is it possible to determine (at runtime) if a function has been implemented?

One of Objective C's primary features is simple introspection. A typical use of this functionality is the ability to check some method (function), to make sure it indeed exists, before calling it.
Whereas the following code will throw an error at runtime (although it compiles just fine (Apple LLVM version 7.0.2 (clang-700.1.81)))...
#import Foundation;
#interface Maybe : NSObject + (void) maybeNot; #end
#implementation Maybe #end
int main (){ [Maybe maybeNot]; }
By adding one simple condition before the call...
if ([Maybe respondsToSelector:#selector(maybeNot)])
We can wait till runtime to decide whether or not to call the method.
Is there any way to do this with "standard" C (c11) or C++ (std=c14)?
i.e....
extern void callMeIfYouDare();
int main() { /* if (...) */ callMeIfYouDare(); }
I guess I should also mention that I am testing/using this is in a Darwin runtime environment.
On GNU gcc / Mingw32 / Cygwin you can use Weak symbol:
#include <stdio.h>
extern void __attribute__((weak)) callMeIfYouDare();
void (*callMePtr)() = &callMeIfYouDare;
int main() {
if (callMePtr) {
printf("Calling...\n");
callMePtr();
} else {
printf("callMeIfYouDare() unresolved\n");
}
}
Compile and run:
$ g++ test_undef.cpp -o test_undef.exe
$ ./test_undef.exe
callMeIfYouDare() unresolved
If you link it with library that defines callMeIfYouDare though it will call it. Note that going via the pointer is necessary in Mingw32/Cygwin at least. Placing a direct call callMeIfYouDare() will result in a truncated relocation by default which unless you want to play with linker scripts is unavoidable.
Using Visual Studio, you might be able to get __declspec(selectany) to do the same trick: GCC style weak linking in Visual Studio?
Update #1: For XCode you can use __attribute__((weak_import)) instead according to: Frameworks and Weak Linking
Update #2: For XCode based on "Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)" I managed to resolve the issue by compiling with the following command:
g++ test_undef.cpp -undefined dynamic_lookup -o test_undef
and leaving __attribute__((weak)) as it is for the other platforms.
If you can see a function of an object (not pointer) is called in a source code and the code is compiled successfully - then the function does exist and no checking needed.
If a function being called via a pointer then you assume your pointer is of type of the class that has that function. To check whether it's so or not you use casting:
auto* p = dynamic_cast<YourClass*>(somepointer);
if (p != nullptr)
p->execute();
C++ or C don't have introspection. You could add some with your additional layer (look at Qt metaobject, or GTK GObject introspection for examples); you might consider customizing GCC with MELT to get some introspection... (but that would take weeks). You could have some additional script or tool which emits C or C++ code related to your introspection needs (SWIG could be inspirational).
In your particular case, you might want to use weak symbols (at least on Linux). Perhaps use the relevant function attribute so code.
extern void perhapshere(void) __attribute__((weak));
if (perhapshere)
perhapshere();
and you might even make that shorter with some macro.
Maybe you just want to load some plugin with dlopen(3) and use dlsym(3) to find symbols in it (or even in the whole program which you would link with -rdynamic, by giving the NULL path to dlopen and using dlsym on the obtained handle); be aware that C++ uses name mangling.
So you might try
void*mainhdl = dlopen(NULL, RTLD_NOW);
if (!mainhdl) { fprintf(stderr, "dlopen failed %s\n", dlerror());
exit(EXIT_FAILURE); };
then later:
typedef void voidvoidsig_t (void); // the signature of perhapshere
void* ad = dlsym(mainhdl, "perhapshere");
if (ad != NULL) {
voidvoidsig_t* funptr = (voidvoidsig_t*)ad;
(*funptr)();
}