I am working through the LLVM Kaleidoscope tutorial. Everything is working fine except for local externs (as opposed to things like the math functions).
[c34n10 kaleidoscope] ./toy
ready> extern sin(x); sin(1);
ready> Read extern:
declare double #sin(double)
ready> ready> Evaluated to 0.841471
ready> extern putchard(x); putchard(120);
ready> Read extern:
declare double #putchard(double)
ready> ready> Failure value returned from cantFail wrapped call
UNREACHABLE executed at /gpfs/loomis/project/fas/manohar/emb99/llvm/include/llvm/Support/Error.h:732!
Aborted (core dumped)
putchard is declared in my code, per the tutorial, as
/// putchard - putchar that takes a double and returns 0.
extern "C" DLLEXPORT double putchard(double X) {
fputc((char)X, stderr);
return 0;
}
Other posts online suggest that this issue could be caused by not compiling with -rdynamic, but I am.
The actual error is occuring with the following code
auto ExprSymbol = TheJIT->findSymbol("__anon_expr");
assert(ExprSymbol && "Function not found");
// cast to double-returning function
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());
and some investigation with GDB reveals that the hasError flag of ExprSymbol.getAddress() is true, which is why the cantFail is failing. As to why that flag is set, I'm at a loss.
It appears not to be an issue with the function itself: from within GDB, I can successfully run call putchard(120), so the symbol definitely exists in the executable.
Finally, my makefile looks like
LIBS=core orcjit native analysis executionengine instcombine object runtimedyld scalaropts support
FLAGS=`llvm-config --cxxflags --ldflags --system-libs --libs $(LIBS)`
%: %.cpp
clang++ -v -g3 -O0 $^ -o $# $(FLAGS) -rdynamic
I ran into exactly the same issue in LLVM 8.
The problem is the symbol resolver doesn't try to find the requested symbol in local process's address, and an Expected<T> requires mandatory checking for errors.
I changed KaleidoscopeJIT.h a bit to get over it.
Replace the KaleidoscopeJIT's constructor with this one:
KaleidoscopeJIT()
: Resolver(createLegacyLookupResolver(
ES,
[this](const std::string &Name) {
auto symbol = ObjectLayer.findSymbol(Name, true);
if (!symbol)
{
if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
return JITSymbol(SymAddr, JITSymbolFlags::Exported);
}
return symbol;
},
[](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })),
TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
ObjectLayer(ES,
[this](VModuleKey) {
return ObjLayerT::Resources{
std::make_shared<SectionMemoryManager>(), Resolver};
}),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
}
The only change is, if no symbol is found after calling ObjectLayer.findSymbol(), it will turn to RTDyldMemoryManager::getSymbolAddressInProcess() to find and create the JITSymbol object.
Related
My end goal is to call some C++ functions from within R, here is a MNWE of where I'm hitting a roadblock. If I'm reading the room correctly, I seem to get a segfault when I call my function with .Call but when I call it with .C everything works fine.
Here is my short C++ function
// test.cpp
#include <iostream>
extern "C" void fnTest() {
std::cout << "Hello" << std::endl;
}
Which I then compiled with
R CMD SHLIB -o test.so test.cpp
Which gave the following output:
g++ -std=gnu++11 -shared -L/usr/lib64/R/lib -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -o te
st.so test.o -L/usr/lib64/R/lib -lR
Now within R I did
> dyn.load("test.so")
> .C("fnTest")
Hello
list()
> .Call("fnTest")
Hello
*** caught segfault ***
address 0x30, cause 'memory not mapped'
Possible actions:
1: abort (with core dump, if enabled)
2: normal R exit
3: exit R without saving workspace
4: exit R saving workspace
Selection:
The documentation that I read for these two functions is here and didn't seem to indicate much of a difference in the calling format of the two functions.
I tried several other variations (e.g. I was was able to pass arguments successfully to .C but not .Call) and didn't have any success.
What is the proper way to .Call a C++ function from within R?
Some notes on my eventual use case beyond this minimal example, hopefully this is not an XY problem:
I have a project with many complicated dependencies which I know how to build with CMake but not directly from g++. I was able to build a shared library from this project that I could then link into an "R compatible" shared library (R CMD SHLIB -o test.so test.cpp -L/path/to/my/lib/ -l my_lib_name) which I was able to dyn.load() into my R environment. At that point I then ran into the above .C vs. .Call issue.
From reading some additional documentation (that I should have found on the first pass), I believe that you cannot .Call a function that has a return type of void.
I could not find an explicit mention of this, but no example in the documentation (e.g. this section) listed a return type other than SEXP and at one point the documentation states that:
All the R objects you will deal with will be handled with the type SEXP
On the other hand, as documented in the Interface functions .C and .Fortran section, any function that you .C must have a return type of void:
Note that the compiled code should not return anything except through its arguments: C functions should be of type void and Fortran subprograms should be subroutines.
Here are some examples that can be compiled as in the OP. It didn't seem like there was a default "null" return type for .Call'ed functions, but allocVector(REALSXP, 0) R_NilValue seemed to work well.
// test.cpp
#include <R.h>
#include <Rinternals.h>
extern "C" void fnPrintC() {
Rprintf("Hello world!\n");
}
extern "C" SEXP fnPrintCall() {
Rprintf("Hello world!\n");
// return allocVector(REALSXP, 0);
return R_NilValue;
}
extern "C" SEXP fnAddCall(SEXP a, SEXP b) {
double* xa = REAL(a);
double* xb = REAL(b);
SEXP ans = allocVector(REALSXP, 2);
REAL(ans)[0] = *xa + *xb;
REAL(ans)[1] = *xa - *xb;
return ans;
}
Here they are called from R. Note we can send the (void) output to the dummy variable x if we don't want to see it.
> dyn.load("test.so")
> x <- .C("fnPrintC")
> Hello world!
> x <- .Call("fnPrintCall")
> Hello world!
> .Call("fnAddCall", 4, 3)
> [1] 7 1
In general, the documentation linked above was pretty helpful, I recommend starting there for anyone with a similar question, I certainly wish I'd read it more thoroughly earlier on.
I run an up to date debian testing (with kernel 4.19).
Helpers are not found on my system (but they exist in the header, Qt jumps to them)
#include "bpf/bpf.h"
int main (){
int r = bpf_create_map(BPF_MAP_TYPE_ARRAY,1,1,1,0);
return 0;
}
Compilation results in
undefined reference to `bpf_create_map(bpf_map_type, int, int, int, unsigned int)'
compiled with
g++ -c -pipe -g -std=gnu++1z -Wall -W -fPIC -DQT_QML_DEBUG -I. -I../../Qt/5.13.0/gcc_64/mkspecs/linux-g++ -o main.o main.cpp
g++ -lbpf -o server main.o
Same result with
g++ main.cpp -lbpf -o out
I have the libbpf-dev installed as well and i have the associated libraries (a and so).
What is wrong?
Update
even the following code won't work
#include <linux/bpf.h>
int main (){
//int r = bpf_create_map(BPF_MAP_TYPE_ARRAY,1,1,1,0);
bpf_attr attr = {};
attr.map_type = BPF_MAP_TYPE_ARRAY;
attr.key_size = 1;
attr.value_size = 1;
attr.max_entries = 1;
bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
return 0;
}
results in
error: 'bpf' was not declared in this scope
Update2:
BTW, key size is mandated to be 4 and not 1; but it is a point aside, that was unrelated to my problem here.
Namespace issue due to compiling in C++, you probably want:
extern "C" {
#include "bpf/bpf.h"
}
int main()...
Regarding your second error (error: 'bpf' was not declared in this scope), this is not directly related to libbpf, this is because there is no function simply called bpf() to actually perform the syscall. Instead you have to use the syscall number. For example, libbpf defines the following:
static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
unsigned int size)
{
return syscall(__NR_bpf, cmd, attr, size);
}
... and uses sys_bpf() after that, the same way you try to call bpf() in your sample.
For the record, “BPF helpers” often designates BPF functions that you call from within a BPF program, which is not the case here. Hence some confusion in the comments, I believe.
Including the following statement in my code
main_module->dump(); // main_module is of type llvm::Module*
causes the following linker error:
undefined reference to 'llvm::Module::dump() const'
The dump method resides in /usr/lib/llvm-5.0/include/llvm/IR/Module.h
I checked stack overflow (Using llvm::Function::dump(), linker gives "undefined reference to `llvm::Value::dump() const'"), and it seems we get this error when the linker isn't fed the libraries in correct order. However, I clearly have the libraries in the end in my compilation command:
clang++-5.0 -g -O3 main.cpp -o main llvm-config-5.0 --cxxflags --ldflags --system-libs --libs core mcjit native
Any help is appreciated.
The weird thing is, the linker figured out that the type of the dump method. It clearly went in the include file. So why would it call it an undefined reference?
Code I am trying to run:
`
# include "llvm/IR/LLVMContext.h"
# include "llvm/IR/Module.h"
# include "llvm/IR/IRBuilder.h"
# include <iostream>
using namespace llvm;
static LLVMContext ctxt;
static IRBuilder<> builder(ctxt);
int main(int argc, char** argv) {
Module* main_module = new Module("main_module", ctxt);
std::cout << main_module->getModuleIdentifier() << "\n";
FunctionType* func_type = FunctionType::get(builder.getInt32Ty(), false);
Function* main_func = Function::Create(func_type,Function::ExternalLinkage, "main", main_module);
if (main_module->getFunction("main")) {
std::cout << "Found function!\n";
}
main_module->dump(); // need this for debugging and testing reasons with LLVM
return 0;
}
In addition to the solution that Subrat provided, you can adjust your code to avoid calling dump. You can achieve the same thing by calling:
main_module->print(llvm::outs(), nullptr);
Similarly, if you want to dump a LLVM function, you can write:
main_func->print(llvm::outs());
Actually, as of LLVM 5.0.0, this is how the dump() function is implemented.
Seems like the definition for dump is in ASMWriter.cpp, which seems to be depracated.
Also, ASMWrite.cpp's debug method refers to dbgs() which is in debug.cpp
I fixed the problem by copying over debug.cpp and the Module::dump() (from ASMWriter.cpp--since I don't need the whole code, only a specific subroutine from this file) routine and putting it in my cpp file.
I have a header (only) file constants.h, where I define all the constant variables, to be used later in the library. However, there is one variable, which I would like to define run-time in an implementation file. I tried to do something like this:
constant.hpp
extern const unsigned int numTests;
somewhere else in run.cpp
const unsigned int numTests = 10;
and, then yet another file tester.cpp uses
if ( n < numTests) {
// do something
}
Now, when I compile it, I get a linker error in tester.o as undefined symbol numTests. I sort of understand why this is happening: the tester.cpp includes constants.hpp and not the run.cpp and so, it can not find the constant numTests initialized in run.cpp.
Is there any better way to do it?
TIA,
Nikhil
Make sure you are compiling both run.cpp and tester.cpp when you compile your program and you won't get a linker error.
You need to link run.o when creating the executable:
g++ -o tester tester.cpp run.o ; for GNU C++
(Check your own compiler's command line switches if you're not using GNU C++)
Suppose we have the following code:
#if !defined(__cplusplus)
# error This file should be compiled as C++
#endif
#include <stdio.h>
#include <string>
//#define USE_CXX_CLASS
#ifdef USE_CXX_CLASS
class SomeClass
{
public:
SomeClass() {}
~SomeClass() {}
std::string GetSomeString()
{
// case #1
}
};
#endif // USE_CXX_CLASS
int foo()
{
// case #2
}
int
main (int argc, char *argv[])
{
(void)argc;
(void)argv;
#ifdef USE_CXX_CLASS
SomeClass someInstance;
someInstance.GetSomeString();
#endif // USE_CXX_CLASS
foo();
return 0;
}
And suppose that it were to be compiled the C++ compiler (and not the C compiler) from GCC version 4.2.1 with the options -Wreturn-type -Werror=return-type. If the above code is compiled as is without first uncommenting the //#define USE_CXX_CLASS line above, then you will see a warning but no error:
.../gcc-4.2.1/bin/g++ -g -fPIC -Wreturn-type -Werror=return-type test.cpp -c -o test.o
test.cpp: In function 'int foo()':
test.cpp:26: warning: control reaches end of non-void function
But if the //#define USE_CXX_CLASS line is uncommented, then the warning is treated as an error:
.../gcc-4.2.1/bin/g++ -g -fPIC -Wreturn-type -Werror=return-type test.cpp -c -o test.o
test.cpp: In member function 'std::string SomeClass::GetSomeString()':
test.cpp:18: error: no return statement in function returning non-void [-Wreturn-type]
gmake: *** [test.o] Error 1
Yes, one is a non-member function (case #2), and the other is a C++ function (case #1). IMO, that should not matter. I want both conditions treated as an error, and I don't want to add -Werror or -Wall at this point in time (probably will do so later, but that is out of scope of this question).
My sub-questions are:
Is there some GCC switch that I am missing that should work? (No I do not want to use #pragma's.)
Is this a bug that has been addressed in a more recent version of GCC?
For reference, I have already poured through other similar questions already, including the following:
Why does flowing off the end of a non-void function without returning a value not produce a compiler error?
C question: no warning?
Is a return statement mandatory for C++ functions that do not return void?
It has been fixed, it works well with g++ 9.3: both member functions and free functions are treated as error with -Wall -Werror=return-type
I do see an error even w/o the USE_CXX_CLASS flag. i.e. g++ is consistent with the error for both class member functions and non member functions.
g++ (GCC) 4.4.3 20100127 (Red Hat 4.4.3-4)
It seems to me that what you need is a shell script wrapper around gcc.
Name it something like gcc-wrapper and g++-wrapper.
In your Makefile set CC and CXX to the wrappers.
Have the wrapper invoke GCC and pipe its output to another program which will search for your desired warning strings.
Have the search program exit with an error when it finds the warning.