0

I was curious this morning to see if I could obtian and understand the machine instructions generated for calculating a mathematical function such as sin, which as far as I am aware there is no machine instruction (in x86-64) for computing.

I first went to Godbolt and tried to obtian the disassembly for this:

// Type your code here, or load an example.
#include <cmath>
int mysin(float num) {
    float result = sin(num);
    return result;
}

I found that the output sets up some registers for a function call and then does call sin.

I then went and searched my local machine for the cmath headers. I found one in /usr/include/c++/10/cmath.h

This header calls another function: __builtin_sin.

My guess would be that the gcc compiler sees this identifier and substitutes it for some set of machine instructions which is somehow "baked into" the gcc compiler itself. Not sure if I am correct about that however.

I did a search of my system for the string __builtin_sinf and it doesn't look like there is any text file on the system which contains source code (C, asm or otherwise) which might then be used by a compiler.

Can anyone offer any explaination as to what __builtin_sinf is, where it is located if it exists in a file on my system, and finally how to obtain the disassembly of this function?

FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225

1 Answers1

4

If you do not have the source code for the compiler on your system, then you probably do not have the source code for __builtin_sin because what to do for __builtin_sin is built into the compiler.

__builtin_sin is not an instruction to the compiler to replace it with a call to a sin routine. It tells the compiler that the operation of the standard C library sin function is desired, with all the semantics of the sin function defined by the C standard. This means the compiler does not have to replace a use of __builtin_sin with a call to sin or a call to any other function. It may replace it with whatever code is appropriate. For example, given some __builtin_sin(x), if the compiler can determine the value of x during compilation, it can calculate sin(x) itself and replace __builtin_sin(x) with that value. Alternatively, the compiler can compile __builtin_sin(x) into assembly language that computes sin. Or it can compile __builtin_sin(x) into a call to the sin routine. It could also compile __builtin_sin(x) to a single machine instruction, such as fsin. (However, fsin is a primitive instruction with some limitations, particularly on argument domain, and is generally not suitable to serve as a sin function by itself.)

So there is no source file that contains the implementation of __builtin_sin other than the compiler’s source code. And, while that source code might contain information about an inline implementation of sin that the compiler uses, that information might not be in the form of assembly language for your target processor; it might be in the form of an internal compiler language specifying what operations to perform to calculate sin. (This is called an intermediate representation.)

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • > *Or it can compile __builtin_sin(x) into a call to the sin routine.* Isn't this a circular argument? What do you mean by "sin routine" here? I am guessing not the same `sin(x)` C++ function. – FreelanceConsultant Jun 06 '22 at 11:07
  • @FreelanceConsultant: “The `sin` routine” means the `sin` routine in the standard C library. – Eric Postpischil Jun 06 '22 at 12:12
  • Ok, so a C routine which I guess is different to the C++ routines which I found in the directory path I gave in the question? – FreelanceConsultant Jun 06 '22 at 16:54
  • This raises another question actually: Where might I find the C routine, if such a thing exists on my system? – FreelanceConsultant Jun 06 '22 at 17:00
  • 1
    @FreelanceConsultant: In `/lib/libm.so`. You can disassemble the binary, or you can look at glibc's source code, if you want to see what code runs for runtime-variable values where the compiler can't do constant-propagation through it. – Peter Cordes Jun 06 '22 at 17:48
  • Typically, one implementation of `sin` is used by both C and C++ implementations. [This answer](https://stackoverflow.com/questions/2284860/how-does-c-compute-sin-and-other-math-functions) has information about some implementations. An implementation that Apple used is [here](https://opensource.apple.com/tarballs/Libm/) in Libm-315.tar.gz, in the file Source/Intel/sincostan.c. – Eric Postpischil Jun 06 '22 at 17:54
  • @PeterCordes I've downloaded glibc from github and I'm completely baffled by the source. I assume I should be looking in the `math` subdirectory. I haven't found anything in there which is obviously source code for the `sin` routine. That includes looking at the makefile, which I can't honestly say I understood in detail because of the heavy use of macros – FreelanceConsultant Jun 06 '22 at 18:38
  • 1
    Here is sin https://github.com/bminor/glibc/blob/master/sysdeps/ieee754/dbl-64/s_sin.c#L200 – KamilCuk Jun 06 '22 at 18:55
  • 1
    woboq has a somewhat out of date copy of the source, but a nice browser for navigating `#include` as a hyperlink and a good search. https://code.woboq.org/userspace/glibc/sysdeps/x86_64/fpu/multiarch/s_sin-fma.c.html seems to include https://code.woboq.org/userspace/glibc/sysdeps/ieee754/dbl-64/s_sin.c.html . – Peter Cordes Jun 06 '22 at 18:57