I have a instruction in my code calling function __atomic_add_fetch. When I compile this code, I am getting compilation error as below
error: undefined reference to '__atomic_fetch_add_8'
I really could not understand why it is throwing undefined reference to __atomic_fetch_add_8 when I am calling __atomic_add_fetch. Could somebody please help me understand what exactly happening while compiling this code?
Note: I am specifically looking to understand "what is internally happening that translates __atomic_add_fetch into __atomic_fetch_add_8". Not the solution to fix compilation issue.
You should be using the standardized atomic_fetch_add.
In any case, it looks like your __atomic_fetch_add with the given argument type (presumably an 8-byte integer) cannot be resolved to an assembly instruction(s) on your platform so it is getting resolved to a function call for which you'll need to link libatomic (-latomic).
Edit with details:
On gcc, __atomic_fetch_add appears to be the compiler built in used to implement stdatomic.h's atomic_fetch_and_explicit (which is just a simple macro name for it). As I've noted, you should really be using the standard name atomic_fetch_add_explicit, not the nonportable implementation detail that __atomic_fetch_add is.
Regardless, the issue seems to be that gcc and clang don't implement atomic_fetch_and_explicit with instructions on ARM (unlike on ARM64 or x86-64) but instead they generate a call to a (global-lock-using) function from the libatomic library. The name of the function seems to be derived from the number of bytes in the integer you're trying to fetch_add to
(__atomic_fetch_add_8 if you're fetch_adding to _Atomic uin64_t
__atomic_fetch_add_4 if you're fetch_adding to _Atomic uin32_t, etc.).
https://gcc.godbolt.org/z/S67g7b
Related
So I went through this video - https://youtu.be/e4ax90XmUBc
Now, my doubt is that if C++ is compiled language, that is, it goes through the entire code and translates it, then if I do something like
void main() {
int a;
cout<<"This is a number = "<<a; //This will give an error (Why?)
a = 10;
}
Now, answer for this would be that I have not defined the value for a, which I learned in school. But if a compiler goes through the entire code and then translates it then I think it shouldn't give any error.
But by giving an error like this, it looks to me as if C++ is a interpreted language.
Can anyone put some light on this and help me solve my dilemma here?
Technically, the C++ standard doesn't mandate that the compiler has to compile C++ into machine code. As an example LLVM Clang first compiles it to IR (Intermediate Representation) and only then to machine code.
Similarly, a compiler could embed a copy of itself in a program that it compiles and then, when the program is executed compile the program, immediately invoke it and delete the executable afterwards which in practice would be very similar to the program being interpreted. In practice, all widely used C++ compilers parse and assemble programs beforehand.
Regarding your example, the statement "This will give an error" is a bit ambiguous. I'm not sure if you're saying that you're getting a compile-time error or a runtime error. As such, I will discuss both possibilities.
If you're getting a compile time error, then your compiler has noticed that your program has undefined behaviour. This is something that you always want to avoid (in some cases, such as when your application operates outside the scope of the C++ Standard, such as when interfacing with certain hardware, UB occurs by definition, as certain behaviour is not defined by the Standard). This is a simple form of static analysis. The Standard doesn't mandate the your compiler informs you of this error and it would usually be a runtime error, but your compiler informed you anyway because it noticed that you probably made a mistake. For example on g++ such behaviour could be achieved by using the -Wall -Werror flags.
In the case of the error being a runtime error then you're most likely seeing a message like "Memory Access Violation" (on Windows) or "Signal 11" (on Linux). This is due to the fact that your program accessed uninitialized memory which is Undefined Behaviour.
In practice, you wouldn't most likely get any error at all at runtime. Unless the compiler has embedded dynamic checks in your program, it would just silently print a (seemingly) random value and continue. The value comes from uninitialized memory.
Side note: main returns int rather than void. Also using namespace std; considered harmful.
[NOTE: contains repetition of previous question but posted separately as separate issues]
I am compiling a program which is known to compile with ifort using gfortran. However the compiler fails on the line
PARAMETER (POS='^')
with the compile error:
conv_prof.mac:9.21:
Included at conv_prof.f:811:
PARAMETER (POS='^')
1
Error: Can't convert CHARACTER(1) to REAL(4) at (1)
make: *** [conv_prof.o] Error 1
As it turns out the POS parameter is not used (it is likely a legacy parameter) so I may simply uncomment this line to compile, but I would like to know if anyone might have any idea why this is an issue in gfortran and not ifort?
Cheers,
Derek
The Intel compiler is the descendant of a long line of Fortran compilers. Its ancestors implemented all sorts of non-standard behaviour and, in the true spirit of Fortran, the latest versions of the compiler ought to compile the most ancient codes. You can often tell ifort to warn of non-standard features in your codes by judicious use of compiler flags.
gfortran, on the other hand, does not (by default) accept much in the way of non-standard syntax, other than those forms of non-standard syntax which have been so widely used that many unsuspecting programmers think that they are standard forms (eg real*4 and the like).
Your snippet looks to me to come from the days prior to FORTRAN77 when the language didn't really acknowledge the existence of such new-fangled ideas as non-numeric variables. In this case I recommend that you follow gfortran in disallowing this code, rather than Intel Fortran.
The specific extension here is that ifort allows a program to "assign" a character value into a real object. Perhaps it was intended to use this extension - but a more likely explanation is that a type declaration statement for the parameter pos is missing prior to the PARAMETER statement.
Technically I don't think the standard requires a diagnostic in this case (this isn't a violation of the syntax rules or constraints of the standard - it is a violation of the requirements placed on the program in the body text), but you'll get a diagnostic from ifort if you turn on standards checking (/stand or -stand, depending on your platform).
I'm looking to write a tool using Clang. The details are fairly immaterial, but what I'm looking to do is get an llvm type from Clang. For example, I'd like to go from "printf" to llvm::Function*, and "size_t" to a llvm::Type*. But I can't find any functions in Clang that give out these functions. I've decided that I can ask Clang to mangle the names, and then ask the llvm::Module* for the data- but I can't find how to get an llvm::Module* that corresponds to a Clang invocation.
How can I get the internal LLVM data from Clang?
Ultimately, the code generation APIs are not part of Clang's public API. This is for good reason, because they are awful.
However, you can create a clang::CodeGen::CodeGenModule, which you can use to codegen a given TU into a provided llvm::Module. Then, you can get the mangled name of a symbol by using the getMangledName function on the CodeGenModule.
However, do not attempt to use the provided functions for converting from a clang::QualType to an llvm::Type*- they are unusably broken. The only viable strategy I have found for reliably performing this conversion is to find a function with a signature, for example, a member function, and then query the Module for the type of that parameter, for example, this. But this is pretty ABI-specific and a nasty hack. You can also compute the LLVM type name that Clang generates for a given type and search for it in the module, but this is not always successful.
In general, you cannot. clang internals are made in layers as well. So, you cannot simply grab a piece of AST and say 'Hey, give me a function'. AST is converted to LLVM IR at the IR generation step module at a time. This way we can be sure everything is parsed and semantically correct and complete.
So, if you really need all this sort of thing, then you need to hook into clang really late, after IR generation and try to operate on loosely coupled AST and LLVM IR at that time.
Consider the following code (this is not pthread specific; other examples, such as those involving the realtime library, exhibit similar behavior):
#define _GNU_SOURCE
#include <pthread.h>
inline void foo() {
static cpu_set_t cpuset;
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
}
int main(int argc, char *argv[]) { }
This is a valid program in C and in C++. So I save the contents of this to testc.c and testcpp.cpp and try to build.
When I build in C++ I get no error. When I build in C I get an undefined reference error. Now, this error occurs in -O1 and in -O3. Is there anyway to instruct gcc to do the right thing (see that foo is unused and skip the requirement for a definition of pthread_setaffinity_np)?
EDIT: I thought it was obvious from context, but the error message is:
/tmp/ccgARGVJ.o: In function `foo':
testc.c:(.text+0x17): undefined reference to `pthread_setaffinity_np'
Note that since foo isn't being referenced in the main path, g++ correctly ignores the function entirely but gcc does not.
EDIT 2: Let me try this one more time. The function foo, and the subsequent call to pthread_setaffinity_np, is unused. The main function is empty. Just look at it! Somehow, g++ figured out that foo did not need to be included, and subsequently the build process did not trip up when we intentionally omitted -lpthread (and checking the exported symbols with nm confirms that neither foo nor reference to pthread_setaffinity_np were needed). The resultant output from gcc didn't pick up on that fact.
I am asking this question because the C++ and the C frontends seem to give different results on the same input. This doesn't seem to be an ld issue prima facie because I would expect both paths to give the same linking error, which is why I emphasized that it seems to be a compiler issue. If both C++ and C gave problems, then yes I would agree that its a linking issue.
Well, apparently your program contains an error: you declare and call function pthread_setaffinity_np, but you never define it. Apparently you forgot to supply the library that contains the definition. This is an error in both C and C++.
In other words, this is not a valid program in C and in C++. It violates the One Definition Rule of C++ (and whatever the similar rule is called in C).
The rest depends on whether the compiler will catch this error and issue a diagnostic message for it. While formally the compiler is supposed to catch it, in reality linking errors are not always caught by the compilation process (in extended sense of the term, i.e. including linking as well).
Whether they are caught or not might depend on many factors. In this particular case the factor that matters is apparently the difference between the properties of inline functions of C and C++ languages. (And yes, they are really different between C and C++). I would guess that in C++ mode the compiler decided that this inline function does not need the actual body, while in C mode it decided to generate the body anyway.
So, again, if this program, somehow successfully compiles in some circumstances, it is only because you got lucky. You seem to believe that a function that is not called is supposed to be "ignored entirely". Neither C nor C++ make such guarantees. Assuming that the definition of pthread_setaffinity_np is indeed missing, your program is invalid in both C and C++. For this reason, the compiler that refused to compile it is actually the one with the correct behavior.
Taking the above into account, you might want to ask yourself whether you really care about why you got different error reports in C and C++ modes. If you do, it will require some research into the internal mechanics of that specific implementation and won't have much to do with the languages themselves.
In C, the inline keyword does not affect the linkage of the function. Thus foo has external linkage, and cannot be optimized out because it might be called from another translation unit. If the compiler/assembler put functions in their own individual sections and the linker is able to discard unneeded function sections at link time, it might be able to avoid a linking error, but to be correct, since this program references pthread_setaffinity_np, it must contain a definition for that function somewhere anyway, i.e. you must use -lpthread or equivalent.
In C++, inline functions have internal some weird pseudo-external linkage by default, so gcc optimized it out. See the comments for details.
In short, the lack of an error in certain configurations is a failure of gcc to diagnose an invalid program. It's not the behavior you should expect.
The other lesson you should take away from this is that C and C++ are nowhere near the same thing. Choose which one you're writing and stick to it! Don't try to write code that's "interchangeable" between the two or you're likely to make it subtly incorrect in both...
inline is only a suggestion, not something a compiler is obligated to listen to, so it can't assume that foo is not used in another compilation unit.
But, yeah, it would be nice to know exactly which is the undefined reference, given that you didn't post the error, and odd that it's shows up in C and not C++ compilation.
foo might not be used in your source code, but it's almost certainly referenced elsewhere in the build process and consequently it needs to be compiled.
Especially since a lot of optimization occur in the linking process, because the linker can determine that a function is "dead" and can be discarded.
If, internally, the linker decides to assemble the entire program as one pass, and then optimization in another, I would expect you to see this error (how can it assemble the whole program?)
Further, if the function is to be exported then it most certainly has to be compiled, linked, and end up in the output.
It sounds like you're relying on compiler/linker specific behavior.
Using gcc, when I ask for an object/variable's type using typeid, I get a different result from the type_info::name method from what I'd expect to get on Windows. I Googled around a bit, and found out that RTTI names are implementation-specific.
Problem is, I want to get a type's name as it would be returned on Windows. Is there an easy way to do this?
If it's what you're asking, there is no compiler switch that would make gcc behave like msvc regarding the name returned by type_info::name().
However, in your code you can rely on the gcc specific __cxa_demangle function.
There is in fact an answer on SO that addresses your problem.
Reference: libstdc++ manual, Chapter 40. Demangling.
c++ function names really include all the return and argument type information as well as the class and method name. When compiled, they are 'mangled' into a standard form (standard for each compiler) that can act as an assembler symbol and includes all the type information.
You need to run a function or program to reverse this mangling, called a demangler.
try running
c++filt myoutput.txt
on the output of the function. This demangles the real symbol name back into a human readable form.
Based on this other question Is there an online name demangler for C++? I've written a online tool for this: c++filtjs