Path: blob/main/contrib/llvm-project/compiler-rt/lib/builtins/README.txt
35260 views
Compiler-RT1================================23This directory and its subdirectories contain source code for the compiler4support routines.56Compiler-RT is open source software. You may freely distribute it under the7terms of the license agreement found in LICENSE.txt.89================================1011This is a replacement library for libgcc. Each function is contained12in its own file. Each function has a corresponding unit test under13test/Unit.1415A rudimentary script to test each file is in the file called16test/Unit/test.1718Here is the specification for this library:1920http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc2122Please note that the libgcc specification explicitly mentions actual types of23arguments and returned values being expressed with machine modes.24In some cases particular types such as "int", "unsigned", "long long", etc.25may be specified just as examples there.2627Here is a synopsis of the contents of this library:2829typedef int32_t si_int;30typedef uint32_t su_int;3132typedef int64_t di_int;33typedef uint64_t du_int;3435// Integral bit manipulation3637di_int __ashldi3(di_int a, int b); // a << b38ti_int __ashlti3(ti_int a, int b); // a << b3940di_int __ashrdi3(di_int a, int b); // a >> b arithmetic (sign fill)41ti_int __ashrti3(ti_int a, int b); // a >> b arithmetic (sign fill)42di_int __lshrdi3(di_int a, int b); // a >> b logical (zero fill)43ti_int __lshrti3(ti_int a, int b); // a >> b logical (zero fill)4445int __clzsi2(si_int a); // count leading zeros46int __clzdi2(di_int a); // count leading zeros47int __clzti2(ti_int a); // count leading zeros48int __ctzsi2(si_int a); // count trailing zeros49int __ctzdi2(di_int a); // count trailing zeros50int __ctzti2(ti_int a); // count trailing zeros5152int __ffssi2(si_int a); // find least significant 1 bit53int __ffsdi2(di_int a); // find least significant 1 bit54int __ffsti2(ti_int a); // find least significant 1 bit5556int __paritysi2(si_int a); // bit parity57int __paritydi2(di_int a); // bit parity58int __parityti2(ti_int a); // bit parity5960int __popcountsi2(si_int a); // bit population61int __popcountdi2(di_int a); // bit population62int __popcountti2(ti_int a); // bit population6364uint32_t __bswapsi2(uint32_t a); // a byteswapped65uint64_t __bswapdi2(uint64_t a); // a byteswapped6667// Integral arithmetic6869di_int __negdi2 (di_int a); // -a70ti_int __negti2 (ti_int a); // -a71di_int __muldi3 (di_int a, di_int b); // a * b72ti_int __multi3 (ti_int a, ti_int b); // a * b73si_int __divsi3 (si_int a, si_int b); // a / b signed74di_int __divdi3 (di_int a, di_int b); // a / b signed75ti_int __divti3 (ti_int a, ti_int b); // a / b signed76su_int __udivsi3 (su_int n, su_int d); // a / b unsigned77du_int __udivdi3 (du_int a, du_int b); // a / b unsigned78tu_int __udivti3 (tu_int a, tu_int b); // a / b unsigned79si_int __modsi3 (si_int a, si_int b); // a % b signed80di_int __moddi3 (di_int a, di_int b); // a % b signed81ti_int __modti3 (ti_int a, ti_int b); // a % b signed82su_int __umodsi3 (su_int a, su_int b); // a % b unsigned83du_int __umoddi3 (du_int a, du_int b); // a % b unsigned84tu_int __umodti3 (tu_int a, tu_int b); // a % b unsigned85du_int __udivmoddi4(du_int a, du_int b, du_int* rem); // a / b, *rem = a % b unsigned86tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); // a / b, *rem = a % b unsigned87su_int __udivmodsi4(su_int a, su_int b, su_int* rem); // a / b, *rem = a % b unsigned88si_int __divmodsi4(si_int a, si_int b, si_int* rem); // a / b, *rem = a % b signed89di_int __divmoddi4(di_int a, di_int b, di_int* rem); // a / b, *rem = a % b signed90ti_int __divmodti4(ti_int a, ti_int b, ti_int* rem); // a / b, *rem = a % b signed91929394// Integral arithmetic with trapping overflow9596si_int __absvsi2(si_int a); // abs(a)97di_int __absvdi2(di_int a); // abs(a)98ti_int __absvti2(ti_int a); // abs(a)99100si_int __negvsi2(si_int a); // -a101di_int __negvdi2(di_int a); // -a102ti_int __negvti2(ti_int a); // -a103104si_int __addvsi3(si_int a, si_int b); // a + b105di_int __addvdi3(di_int a, di_int b); // a + b106ti_int __addvti3(ti_int a, ti_int b); // a + b107108si_int __subvsi3(si_int a, si_int b); // a - b109di_int __subvdi3(di_int a, di_int b); // a - b110ti_int __subvti3(ti_int a, ti_int b); // a - b111112si_int __mulvsi3(si_int a, si_int b); // a * b113di_int __mulvdi3(di_int a, di_int b); // a * b114ti_int __mulvti3(ti_int a, ti_int b); // a * b115116117// Integral arithmetic which returns if overflow118119si_int __mulosi4(si_int a, si_int b, int* overflow); // a * b, overflow set to one if result not in signed range120di_int __mulodi4(di_int a, di_int b, int* overflow); // a * b, overflow set to one if result not in signed range121ti_int __muloti4(ti_int a, ti_int b, int* overflow); // a * b, overflow set to122one if result not in signed range123124125// Integral comparison: a < b -> 0126// a == b -> 1127// a > b -> 2128129si_int __cmpdi2 (di_int a, di_int b);130si_int __cmpti2 (ti_int a, ti_int b);131si_int __ucmpdi2(du_int a, du_int b);132si_int __ucmpti2(tu_int a, tu_int b);133134// Integral / floating point conversion135136di_int __fixsfdi( float a);137di_int __fixdfdi( double a);138di_int __fixxfdi(long double a);139di_int __fixtfdi( tf_float a);140141ti_int __fixsfti( float a);142ti_int __fixdfti( double a);143ti_int __fixxfti(long double a);144ti_int __fixtfti( tf_float a);145146su_int __fixunssfsi( float a);147su_int __fixunsdfsi( double a);148su_int __fixunsxfsi(long double a);149su_int __fixunstfsi( tf_float a);150151du_int __fixunssfdi( float a);152du_int __fixunsdfdi( double a);153du_int __fixunsxfdi(long double a);154du_int __fixunstfdi( tf_float a);155156tu_int __fixunssfti( float a);157tu_int __fixunsdfti( double a);158tu_int __fixunsxfti(long double a);159tu_int __fixunstfti( tf_float a);160161float __floatdisf(di_int a);162double __floatdidf(di_int a);163long double __floatdixf(di_int a);164tf_float __floatditf(int64_t a);165166float __floattisf(ti_int a);167double __floattidf(ti_int a);168long double __floattixf(ti_int a);169tf_float __floattitf(ti_int a);170171float __floatundisf(du_int a);172double __floatundidf(du_int a);173long double __floatundixf(du_int a);174tf_float __floatunditf(du_int a);175176float __floatuntisf(tu_int a);177double __floatuntidf(tu_int a);178long double __floatuntixf(tu_int a);179tf_float __floatuntixf(tu_int a);180181// Floating point raised to integer power182183float __powisf2( float a, int b); // a ^ b184double __powidf2( double a, int b); // a ^ b185long double __powixf2(long double a, int b); // a ^ b186tf_float __powitf2( tf_float a, int b); // a ^ b187188// Complex arithmetic189190// (a + ib) * (c + id)191192float _Complex __mulsc3( float a, float b, float c, float d);193double _Complex __muldc3(double a, double b, double c, double d);194long double _Complex __mulxc3(long double a, long double b,195long double c, long double d);196tf_float _Complex __multc3(tf_float a, tf_float b, tf_float c, tf_float d);197198// (a + ib) / (c + id)199200float _Complex __divsc3( float a, float b, float c, float d);201double _Complex __divdc3(double a, double b, double c, double d);202long double _Complex __divxc3(long double a, long double b,203long double c, long double d);204tf_float _Complex __divtc3(tf_float a, tf_float b, tf_float c, tf_float d);205206207// Runtime support208209// __clear_cache() is used to tell process that new instructions have been210// written to an address range. Necessary on processors that do not have211// a unified instruction and data cache.212void __clear_cache(void* start, void* end);213214// __enable_execute_stack() is used with nested functions when a trampoline215// function is written onto the stack and that page range needs to be made216// executable.217void __enable_execute_stack(void* addr);218219// __gcc_personality_v0() is normally only called by the system unwinder.220// C code (as opposed to C++) normally does not need a personality function221// because there are no catch clauses or destructors to be run. But there222// is a C language extension __attribute__((cleanup(func))) which marks local223// variables as needing the cleanup function "func" to be run when the224// variable goes out of scope. That includes when an exception is thrown,225// so a personality handler is needed.226_Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions,227uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject,228_Unwind_Context_t context);229230// for use with some implementations of assert() in <assert.h>231void __eprintf(const char* format, const char* assertion_expression,232const char* line, const char* file);233234// for systems with emulated thread local storage235void* __emutls_get_address(struct __emutls_control*);236237238// Power PC specific functions239240// There is no C interface to the saveFP/restFP functions. They are helper241// functions called by the prolog and epilog of functions that need to save242// a number of non-volatile float point registers.243saveFP244restFP245246// PowerPC has a standard template for trampoline functions. This function247// generates a custom trampoline function with the specific realFunc248// and localsPtr values.249void __trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated,250const void* realFunc, void* localsPtr);251252// adds two 128-bit double-double precision values ( x + y )253long double __gcc_qadd(long double x, long double y);254255// subtracts two 128-bit double-double precision values ( x - y )256long double __gcc_qsub(long double x, long double y);257258// multiples two 128-bit double-double precision values ( x * y )259long double __gcc_qmul(long double x, long double y);260261// divides two 128-bit double-double precision values ( x / y )262long double __gcc_qdiv(long double a, long double b);263264265// ARM specific functions266267// There is no C interface to the switch* functions. These helper functions268// are only needed by Thumb1 code for efficient switch table generation.269switch16270switch32271switch8272switchu8273274// This function generates a custom trampoline function with the specific275// realFunc and localsPtr values.276void __trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated,277const void* realFunc, void* localsPtr);278279// There is no C interface to the *_vfp_d8_d15_regs functions. There are280// called in the prolog and epilog of Thumb1 functions. When the C++ ABI use281// SJLJ for exceptions, each function with a catch clause or destructors needs282// to save and restore all registers in it prolog and epilog. But there is283// no way to access vector and high float registers from thumb1 code, so the284// compiler must add call outs to these helper functions in the prolog and285// epilog.286restore_vfp_d8_d15_regs287save_vfp_d8_d15_regs288289290// Note: long ago ARM processors did not have floating point hardware support.291// Floating point was done in software and floating point parameters were292// passed in integer registers. When hardware support was added for floating293// point, new *vfp functions were added to do the same operations but with294// floating point parameters in floating point registers.295296// Undocumented functions297298float __addsf3vfp(float a, float b); // Appears to return a + b299double __adddf3vfp(double a, double b); // Appears to return a + b300float __divsf3vfp(float a, float b); // Appears to return a / b301double __divdf3vfp(double a, double b); // Appears to return a / b302int __eqsf2vfp(float a, float b); // Appears to return one303// iff a == b and neither is NaN.304int __eqdf2vfp(double a, double b); // Appears to return one305// iff a == b and neither is NaN.306double __extendsfdf2vfp(float a); // Appears to convert from307// float to double.308int __fixdfsivfp(double a); // Appears to convert from309// double to int.310int __fixsfsivfp(float a); // Appears to convert from311// float to int.312unsigned int __fixunssfsivfp(float a); // Appears to convert from313// float to unsigned int.314unsigned int __fixunsdfsivfp(double a); // Appears to convert from315// double to unsigned int.316double __floatsidfvfp(int a); // Appears to convert from317// int to double.318float __floatsisfvfp(int a); // Appears to convert from319// int to float.320double __floatunssidfvfp(unsigned int a); // Appears to convert from321// unsigned int to double.322float __floatunssisfvfp(unsigned int a); // Appears to convert from323// unsigned int to float.324int __gedf2vfp(double a, double b); // Appears to return __gedf2325// (a >= b)326int __gesf2vfp(float a, float b); // Appears to return __gesf2327// (a >= b)328int __gtdf2vfp(double a, double b); // Appears to return __gtdf2329// (a > b)330int __gtsf2vfp(float a, float b); // Appears to return __gtsf2331// (a > b)332int __ledf2vfp(double a, double b); // Appears to return __ledf2333// (a <= b)334int __lesf2vfp(float a, float b); // Appears to return __lesf2335// (a <= b)336int __ltdf2vfp(double a, double b); // Appears to return __ltdf2337// (a < b)338int __ltsf2vfp(float a, float b); // Appears to return __ltsf2339// (a < b)340double __muldf3vfp(double a, double b); // Appears to return a * b341float __mulsf3vfp(float a, float b); // Appears to return a * b342int __nedf2vfp(double a, double b); // Appears to return __nedf2343// (a != b)344double __negdf2vfp(double a); // Appears to return -a345float __negsf2vfp(float a); // Appears to return -a346float __negsf2vfp(float a); // Appears to return -a347double __subdf3vfp(double a, double b); // Appears to return a - b348float __subsf3vfp(float a, float b); // Appears to return a - b349float __truncdfsf2vfp(double a); // Appears to convert from350// double to float.351int __unorddf2vfp(double a, double b); // Appears to return __unorddf2352int __unordsf2vfp(float a, float b); // Appears to return __unordsf2353354355Preconditions are listed for each function at the definition when there are any.356Any preconditions reflect the specification at357http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc.358359Assumptions are listed in "int_lib.h", and in individual files. Where possible360assumptions are checked at compile time.361362363