I'm working on a compiler to produce LLVM IR code for a toy language (for a class).
However, I keep getting a strange error: "invalid redefinition of function Main_main". This function is only defined once, as grepping for "Main_main" shows:
$ grep "Main_main" test.ll
declare %Object* #Main_main(%Main*)
%Object* (%Main*) * #Main_main
%vtpm.1 = call %Object*(%Main* ) #Main_main( %Main* %vtpm.0 )
define %Object* #Main_main(%Main* %_self_var) {
The first line is where it's declared, the second is where a pointer to it is stored in a vtable, the third is where it's called, and the fourth is where it's defined. Surely only one of those counts as a definition?
The exact error message:
$ llvm-as test.ll -o test.bc
llvm-as: test.ll:179:17: error: invalid redefinition of function 'Main_main'
define %Object* #Main_main(%Main* %_self_var) {
^
What am I doing wrong, that makes LLVM think this is a redefinition?
The IR you show is syntactically incorrect. Functions declared with declare could not have bodies and even if they could, you are missing curly braces. You should have something like
declare %Object* #Main_main(%Main*)
define %Object* #Main_main(%Main* %_self_var) {
...
}
Also, it seems you are generating textual IR by hand. The canonical way to do that is via C++/C/whatever API. This would ensure code correctness by means of type safety or additional checks.
Related
I am trying to pass my class' function void write_log(String verbosity, Variant message); to another class which will be threading event loop (ev.h). String and Variant are from the godot namespace.
I have used typedef to make write_log into type Logger using the definition typedef void (godot::MQTT::*Logger)(godot::String, godot::Variant);. This definition is stored in the callee class and not the calling class.
The function being called is defined as void initialize(Logger logger); which is then called with the code below.
libumqtt::Client client;
client.initialize(&MQTT::write_log);
My calling class is godot::MQTT and the callee class is libumqtt::Client.
My error occurs when I try to use write_log.
void Client::initialize(Logger write_log) {
...
write_log("error", "Initializing MQTT Client!!! TypeDEF!!!");
...
}
The error message is as below.
➜ Godot-MQTT-Module git:(master) ✗ scons platform=osx bits=64
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o src/MQTT.os -c -g -O2 -arch x86_64 -std=c++17 -fPIC -I. -Igodot-cpp/godot_headers -Igodot-cpp/include -Igodot-cpp/include/core -Igodot-cpp/include/gen -Isrc -Ilibraries/libumqtt/src src/MQTT.cpp
g++ -o src/client.os -c -g -O2 -arch x86_64 -std=c++17 -fPIC -I. -Igodot-cpp/godot_headers -Igodot-cpp/include -Igodot-cpp/include/core -Igodot-cpp/include/gen -Isrc -Ilibraries/libumqtt/src src/client.cpp
src/client.cpp:120:14: error: called object type 'libumqtt::Client::Logger' (aka 'void (godot::MQTT::*)(godot::String, godot::Variant)') is not a function or function pointer
write_log("error", "Initializing MQTT Client!!! TypeDEF!!!");
~~~~~~~~~^
1 error generated.
scons: *** [src/client.os] Error 1
scons: building terminated because of errors.
I have been trying to figure out why I cannot get the compiler to recognize the function pointer, but have had no such luck so far. I've received errors such as not being able to use indirection and so on while messing around with my code.
I also used these links to help me with learning how to use typedef and pass a function pointer:
Typedef Fully Qualified Name With Pointers - http://www.radmangames.com/programming/how-to-use-function-pointers-in-cplusplus
Using vs Typedef - https://www.internalpointers.com/post/differences-between-using-and-typedef-modern-c
Typedef in Header - How do I refer to a typedef in a header file?
Typedef Examples - https://en.wikipedia.org/w/index.php?title=Typedef&oldid=923023181#Function_pointers
What is Typedef - https://www.cprogramming.com/tutorial/typedef.html
Pass A Function Pointer - https://stackoverflow.com/a/9413/6828099
Edit: On uninitialized's mention of my code looking correct, but the amount posted is limited, I am pasting the links to the classes and header files from my repo. These links are marked for this specific commit, so the content won't change even when I update the code. Also, this library is MIT, so you won't have to worry about copyright.
MQTT.cpp
MQTT.hpp
client.cpp
client.hpp
Edit 2: Using this answer, I have checked the type of variable I am trying to use write_log in the callee class and it returns what I expected it to. So, I have no idea why the compiler cannot see that this is a function. I am using C++17 to compile my code and C++14 has the same issue (C++11 breaks on other code before even getting to this, so it doesn't provide useful results).
void (godot::MQTT::*)(godot::String, godot::Variant)
From the limited snippet of code you've posted, there doesn't seem to be any error. However, the gcc/g++ compiler is known to throw this error if there is syntax issues like semicolon etc... in the lines preceding this function call.
To answer my own question, I will be repeating and explaining the code I wrote.
We have two classes which are stored in the two files, MQTT.cpp and Client.cpp. MQTT.cpp has the namespace "godot" and the class name "MQTT" (so, godot::MQTT::). Client.cpp has the namespace "libumqtt" and the class name "Client" (so, libumqtt::Client::).
MQTT has a function that is defined as void write_log(String verbosity, Variant message); It also has the function initialize();. The arguments and return type do not matter for initialize. To initialize the client, I create an object of Client and then call its own method which is also called initialize.
// MQTT.cpp
String MQTT::initialize() {
// ...
// This code will initialize the Client class and pass the function `write_log` to the Client object.
// `write_log` is marked as private in the header file MQTT.hpp.
libumqtt::Client client;
client.initialize(*this, &MQTT::write_log); // Initialize Instance of Client
// ...
}
In Client.hpp, I marked initialize as public and added the line void initialize(godot::MQTT& mqtt_class, Logger logger);. I also added the typedef typedef void (godot::MQTT::*Logger)(godot::String, godot::Variant); so I can just refer to write_log's data type as Logger.
To call the write_log function, I used the below code.
// Client.cpp
void Client::initialize(godot::MQTT& mqtt_class, Logger write_log) {
// ...
// Send Test Log
// Why Invoke? - https://isocpp.org/wiki/faq/pointers-to-members#macro-for-ptr-to-memfn
std::invoke(write_log, mqtt_class, "error", "Initializing MQTT Client!!! TypeDEF!!!");
// ...
}
What I was doing wrong was I was trying to call a pointer to a member function without using invoke. Since I am new to cpp, I wouldn't have known about the fact that I cannot just call a pointer directly if it goes to another function that is not a direct part of my class. Using invoke is easier than trying to use ((object).*(ptrToMember)) which has syntax I do not completely understand yet.
What I did was I created a pointer to my class, godot::MQTT, by grabbing the pointer of the keyword this. I then create a reference to the pointer provided by this through the variable godot::MQTT& mqtt_class. After that, calling the function write_log is as simple as providing the reference to the calling class' object and then the pointer to the function in the calling class, as well as the arguments needed to call the function.
As I am a noob to C++, someone with more experience should edit this sentence out and explain why you need both the reference to the calling object on top of the pointer to the function that needs to be called.
The man page for opt says: "It takes LLVM source files as input, runs the specified optimizations or analyses on it, and then outputs the optimized file or the analysis results".
My Goal: To use the inbuilt optimisation pass -dce available in opt. This pass does Dead Code Elimination
My Source file foo.c:
int foo(void)
{
int a = 24;
int b = 25; /* Assignment to dead variable -- dead code */
int c;
c = a * 4;
return c;
}
Here is what I did:
1. clang-7.0 -S -emit-llvm foo.c -o foo.ll
2. opt -dce -S foo.ll -o fooOpt.ll
What I expect : A .ll file in which the dead code (in source code with the comment) part is eliminated.
What I get: fooOpt.ll is the same as non optimised code foo.ll
I have already seen this SO answer, but I didn't get optimised code.
Am I missing something here? Can someone please guide me on the right path.
Thank you.
If you look at the .ll file generated by clang, it will contain a line like this:
attributes #0 = { noinline nounwind optnone sspstrong uwtable ...}
You should remove the optnone attribute here. Whenever a function has the optnone attribute, opt won't touch that function at all.
Now if you try again, you'll notice ... nothing. It still does not work.
This time the problem is that the code is working on memory, not registers. What we need to do is to convert the allocas to registers using -mem2reg. In fact doing this will already optimize away b, so you don't even need the -dce flag.
I am using the function bfd_find_nearest_line to find the source location of a function (from an executable with debugging symbols --compiled with -g). Naturally one of the arguments is a pointer to the function I want to locate:
boolean
_bfd_elf_find_nearest_line (abfd,
section,
symbols,
offset,
filename_ptr,
functionname_ptr, // <- HERE!
line_ptr)
https://sourceware.org/ml/binutils/2000-08/msg00248.html
After quite a bit of (pure C) boiler plate, I managed this to work with normal functions (where the normal function pointer is casted to *void).
For example, this works:
int my_function(){return 5;}
int main(){
_bfd_elf_find_nearest_line (...,
(void*)(&my_function),
...);
}
The question is if bfd_find_nearest_line can be used to locate the source code of a class member function.
struct A{
int my_member_function(){return 5.;}
};
_bfd_elf_find_nearest_line (...,
what_should_I_put_here??,
...)
Class member function (in this case if type int (A::*)()) are not functions, an in particular cannot be cast to any function pointer, not even to void*. See here: https://isocpp.org/wiki/faq/pointers-to-members#cant-cvt-memfnptr-to-voidptr
I completely understand the logic behind this, how ever the member-function pointer is the only handle from which I have information of a member function in order to make BFD identify the function. I don't want this pointer to call a function.
I know more or less how C++ works, the compiler will generate silently an equivalent free-C function,
__A_my_member_function(A* this){...}
But I don't know how to access the address of this free function or if that is even possible,and whether the bfd library will be able to locate the source location of the original my_member_function via this pointer.
(For the moment at least I am not interested in virtual functions.)
In other words,
1) I need to know if bfd will be able to locate a member function,
2) and if it can how can I map the member function pointer of type int (A::*)() to an argument that bfd can take (void*).
I know by other means (stack trace) that the pointer exists, for example I can get that the free function is called in this case _ZN1A18my_member_functionEv, but the problem is how I can get this from &(A::my_member_function).
Okay, there's good news and bad news.
The good news: It is possible.
The bad news: It's not straight forward.
You'll need the c++filt utility.
And, some way to read the symbol table of your executable, such as readelf. If you can enumerate the [mangled] symbols with a bfd_* call, you may be able to save yourself a step.
Also, here is a biggie: You'll need the c++ name of your symbol in a text string. So, for &(A::my_member_function), you'll need it in a form: "A::my_member_function()" This shouldn't be too difficult since I presume you have a limited number of them that you care about.
You'll need to get a list of symbols and their addresses from readelf -s <executable>. Be prepared to parse this output. You'll need to decode the hex address from the string to get its binary value.
These will be the mangled names. For each symbol, do c++filt -n mangled_name and capture the output (i.e. a pipe) into something (e.g. nice_name). It will give you back the demangled name (i.e. the nice c++ name you'd like).
Now, if nice_name matches "A:my_member_function()", you now have a match, you already have the mangled name, but, more importantly, the hex address of the symbol. Feed this hex value [suitably cast] to bfd where you were stuffing functionname_ptr
Note: The above works but can be slow with repeated invocations of c++filt
A faster way is to do this is to capture the piped output of:
readelf -s <executable> | c++filt
It's also [probably] easier to do it this way since you only have to parse the filtered output and look for the matching nice name.
Also, if you had multiple symbols that you cared about, you could get all the addresses in a single invocation.
Ok, I found a way. First, I discovered that bfd is pretty happy detecting member functions debug information from member pointers, as long as the pointer can be converted to void*.
I was using clang which wouldn't allow me to cast the member function pointer to any kind of pointer or integer.
GCC allows to do this but emits a warning.
There is even a flag to allow pointer to member cast called -Wno-pmf-conversions.
With that information in mind I did my best to convert a member function pointer into void* and I ended up doing this using unions.
struct A{
int my_member_function(){return 5.;}
};
union void_caster_t{
int (A::*p)(void) value;
void* casted_value;
};
void_caster_t void_caster = {&A::my_member_function};
_bfd_elf_find_nearest_line (...,
void_caster.casted_value,
...)
Finally bfd is able to give me debug information of a member function.
What I didn't figure out yet, is how to get the pointer to the constructor and the destructor member functions.
For example
void_caster_t void_caster = {&A::~A};
Gives compiler error: "you can't take the address of the destructor".
For the constructor I wasn't even able to find the correct syntax, since this fails as a syntax error.
void_caster_t void_caster = {&A::A};
Again all the logic behind not being able involves non-sensical callbacks, but this is different because I want the pointer (or address) to get debug information, not callbacks.
I have a test.c file which has this function call:
functiontest(2,x);
I would like to delete this function call (with an llvm pass) and when I try to use removeFromParent() function like this:
calledFunction1->removeFromParent();
this causes LLVM to produce the following error:
Referencing function in another module!
call void #functiontest(i32 2, float %tmp15)
LLVM ERROR: Broken function found, compilation aborted!
I also tried calling eraseFromParent() but this triggers an assert:
Assertion `use_empty() && "Uses remain when a value is destroyed!"' failed.
I would prefer to use removeFromParent()
Any ideas what's wrong ?
First of all, it would be really helpful if you could post a minimal code sample that demonstrates your problem. Otherwise, we can only guess. Some observations though:
Why do you prefer removeFromParent? The call instruction has to be deleted too, that's what eraseFromParent does.
Did you call replaceAllUsesWith before erasing/removing? Otherwise, uses stick around.
Did you remove the function or the call instruction? This may explain the first error message.
I am unable to use lldb to invoke simple, non-templated functions that take string arguments. Is there any way to get lldb to understand the C++ datatype "string", which is a commonly used datatype in C++ programs?
The sample source code here just creates a simple class with a few constructors, and then calls them (includes of "iostream" and "string" omitted):
using namespace std;
struct lldbtest{
int bar=5;
lldbtest(){bar=6;}
lldbtest(int foo){bar=foo;}
lldbtest(string fum){bar=7;}
};
int main(){
string name="fum";
lldbtest x,y(3);
cout<<x.bar<<y.bar<<endl;
return 0;
}
When compiled on Mac Maverick with
g++ -g -std=c++11 -o testconstructor testconstructor.cpp
the program runs and prints the expected output of "63".
However, when a breakpoint is set in main just before the return statement, and attempt to invoke the constructor fails with a cryptic error message:
p lldbtest(string("hey there"))
error: call to a function 'lldbtest::lldbtest(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)' ('_ZN8lldbtestC1ENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE') that is not present in the target
error: The expression could not be prepared to run in the target
Possibly relevant as well, the command:
p lldbtest(name)
prints nothing at all.
Also, calling the constructor with a string literal also failed, the standard way:
p lldbtest("foo")
gives a similar long error:
error: call to a function
'lldbtest::lldbtest(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)' ('_ZN8lldbtestC1ENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE') that is not present in the targeterror: The expression could not be prepared to run in the target
Is there any way to get lldb to understand and use the C++ "string" datatype? I have a number of functions taking string arguments and need a way to invoke these functions from the debugger. On a Mac.
THE PROBLEM
This is due to a subtle problem with your code, that boils down to the following wording from the C++ Standard:
7.1.2p3-4 Function specifiers [dcl.fct.spec]
A function defined within a class definition is an inline function.
...
An inline function shall be defined in every translation unit in which it is odr-used, and shall have exactly the same definition in every case (3.2).
Your constructor, lldbtest(std::string) is defined within the body of lldbtest which means that it will implicitly be inline, which further means that the compiler will not generate any code for it, unless it is used in the translation unit.
Since the definition must be present in every translation unit that potentially calls it we can imagine the compiler saying; "heck, I don't need to do this.. if someone else uses it, they will generate the code".
lldb will look for a function definition which doesn't exist, since gcc didn't generate one; because you didn't use it.
THE SOLUTION
If we change the definition of lldbtest to the following I bet it will work as you intended:
struct lldbtest{
int bar=5;
lldbtest();
lldbtest(int foo);
lldbtest(string fum);
};
lldbtest::lldbtest() { bar=6; }
lldbtest::lldbtest(int) { bar=7; }
lldbtest::lldbtest(string) { bar=8; }
But.. what about p lldbtest(name)?
The command p in lldb is used to print* information, but it can also be used to evaluate expressions.
lldbtest(name) will not call the constructor of lldbtest with a variable called name, it's equivalent of declaring a variable called name of type lldbtest; ie. lldbtest name is sementically equivalent.
Going to answer the asked question here instead of addressing the problem with the op's code. Especially since this took me a while to figure out.
Use a string in a function invocation in lldb in C++
(This post helped greatly, and is a good read: Dancing in The Debugger)