Commit 5d89955543

Jan Philipp Hafer <jan.hafer@rwth-aachen.de>
2022-02-15 14:56:49
compiler_rt: specify goals, organize README and compiler_rt.zig
* goals - zig as linker for object files generated by other compilers - zig-specific runtime features for eventual standardisation * changes - missing routines are marked with `missing` - structure inspired by libgcc docs, but improved order and wording - rename misspelled functions - reorder and rephrase compiler_rt.zig to reflect documentation - potential decimal float or fixed-point arithmetic support: * 'Decimal float library routines' ca. 120 functions * 'Fixed-point fractional library routines' ca. 300 functions thanks to @Vexu for multiple reviews and @scheibo for review
1 parent ecf56d8
Changed files (5)
lib/std/special/compiler_rt/extend_f80.zig
@@ -11,7 +11,7 @@ pub fn __extendhfxf2(a: F16T) callconv(.C) f80 {
     return extendF80(f16, @bitCast(u16, a));
 }
 
-pub fn __extendffxf2(a: f32) callconv(.C) f80 {
+pub fn __extendsfxf2(a: f32) callconv(.C) f80 {
     return extendF80(f32, @bitCast(u32, a));
 }
 
lib/std/special/compiler_rt/README.md
@@ -1,15 +1,267 @@
-This compiler-rt library is ported from [LLVM](http://compiler-rt.llvm.org/).
+If hardware lacks basic or specialized functionality, compiler-rt adds such functionality
+for basic arithmetic(s).
+One such example is 64-bit integer multiplication on 32-bit x86.
 
-It's needed because LLVM emits library calls to compiler-rt when hardware lacks
-functionality, for example, 64-bit integer multiplication on 32-bit x86.
+Goals:
+1. zig as linker for object files produced by other compilers
+   => `function compatibility` to compiler-rt and libgcc for same-named functions
+   * compatibility conflict between compiler-rt and libgcc: prefer compiler-rt
+2. `symbol-level compatibility` low-priority compared to emitted calls by llvm
+   * symbol-level compatibility: libgcc even lower priority
+3. add zig-specific language runtime features, see #7265
+   * example: arbitrary bit width integer arithmetic
+   * lower to call those functions for e.g. multiplying two i12345 numbers together
+   * proper naming + documention for standardizing (allow languages to follow our exmaple)
+
+Current status (tracking libgcc documentation):
+- Integer library routines => almost implemented
+- Soft float library routines => only f80 routines missing
+- Decimal float library routines => unimplemented (~120 functions)
+- Fixed-point fractional library routines => unimplemented (~300 functions)
+- Exception handling routines => unclear, if supported (~32+x undocumented functions)
+- Miscellaneous routines => unclear, if supported (cache control and stack function)
+- No zig-specific language runtime features in compiler-rt yet
 
 This library is automatically built as-needed for the compilation target and
 then statically linked and therefore is a transparent dependency for the
 programmer.
+For details see `../compiler_rt.zig`.
+
+The routines in this folder are listed below.
+Routines are annotated as `type source routine // description`, with `routine`
+being the name used in aforementioned `compiler_rt.zig`.
+`dev` means deviating from compiler_rt, `port` ported, `source` is the
+information source for the implementation, `none` means unimplemented.
+Some examples for the naming convention are:
+- dev source name_routine, name_routine2 various implementations for performance, simplicity etc
+- port llvm compiler-rt library routines from [LLVM](http://compiler-rt.llvm.org/)
+   * LLVM emits library calls to compiler-rt, if the hardware lacks functionality
+- port musl libc routines from [musl](https://musl.libc.org/)
+If the library or information source is uncommon, use the entry `other` for `source`.
+Please do not break the search by inserting entries in another format than `impl space source`.
+
+Bugs should be solved by trying to duplicate the bug upstream, if possible.
+ * If the bug exists upstream, get it fixed upstream and port the fix downstream to Zig.
+ * If the bug only exists in Zig, use the corresponding C code and debug
+   both implementations side by side to figure out what is wrong.
+
+## Integer library routines
+
+#### Integer Bit operations
+- dev HackersDelight __clzsi2          // count leading zeros
+- dev HackersDelight __clzdi2          // count leading zeros
+- dev HackersDelight __clzti2          // count leading zeros
+- dev HackersDelight __ctzsi2          // count trailing zeros
+- dev HackersDelight __ctzdi2          // count trailing zeros
+- dev HackersDelight __ctzti2          // count trailing zeros
+- dev __ctzsi2 __ffssi2                // find least significant 1 bit
+- dev __ctzsi2 __ffsdi2                // find least significant 1 bit
+- dev __ctzsi2 __ffsti2                // find least significant 1 bit
+- dev BitTwiddlingHacks __paritysi2    // bit parity
+- dev BitTwiddlingHacks __paritydi2    // bit parity
+- dev BitTwiddlingHacks __parityti2    // bit parity
+- dev TAOCP __popcountsi2              // bit population
+- dev TAOCP __popcountdi2              // bit population
+- dev TAOCP __popcountti2              // bit population
+- dev other __bswapsi2                 // a byteswapped
+- dev other __bswapdi2                 // a byteswapped
+- dev other __bswapti2                 // a byteswapped
+
+#### Integer Comparison
+- port llvm __cmpsi2        // (a<b)=>output=0, (a==b)=>output=1, (a>b)=>output=2
+- port llvm __cmpdi2
+- port llvm __cmpti2
+- port llvm __ucmpsi2       // (a<b)=>output=0, (a==b)=>output=1, (a>b)=>output=2
+- port llvm __ucmpdi2
+- port llvm __ucmpti2
+
+#### Integer Arithmetic
+- none none __ashlsi3              // a << b unused in llvm, missing (e.g. used by rl78)
+- port llvm __ashldi3              // a << b
+- port llvm __ashlti3              // a << b
+- none none __ashrsi3              // a >> b  arithmetic (sign fill) missing (e.g. used by rl78)
+- port llvm __ashrdi3              // a >> b  arithmetic (sign fill)
+- port llvm __ashrti3              // a >> b  arithmetic (sign fill)
+- none none __lshrsi3              // a >> b  logical    (zero fill) missing (e.g. used by rl78)
+- port llvm __lshrdi3              // a >> b  logical    (zero fill)
+- port llvm __lshrti3              // a >> b  logical    (zero fill)
+- port llvm __negdi2               // -a symbol-level compatibility: libgcc
+- port llvm __negti2               // -a unnecessary: unused in backends
+- port llvm __mulsi3               // a * b  signed
+- port llvm __muldi3               // a * b  signed
+- port llvm __multi3               // a * b  signed
+- port llvm __divsi3               // a / b  signed
+- port llvm __divdi3               // a / b  signed
+- port llvm __divti3               // a / b  signed
+- port llvm __udivsi3              // a / b  unsigned
+- port llvm __udivdi3              // a / b  unsigned
+- port llvm __udivti3              // a / b  unsigned
+- port llvm __modsi3               // a % b  signed
+- port llvm __moddi3               // a % b  signed
+- port llvm __modti3               // a % b  signed
+- port llvm __umodsi3              // a % b  unsigned
+- port llvm __umoddi3              // a % b  unsigned
+- port llvm __umodti3              // a % b  unsigned
+- port llvm __udivmoddi4           // a / b, rem.* = a % b  unsigned
+- port llvm __udivmodti4           // a / b, rem.* = a % b  unsigned
+- port llvm __udivmodsi4           // a / b, rem.* = a % b  unsigned
+- port llvm __divmodsi4            // a / b, rem.* = a % b  signed, ARM
+
+#### Integer Arithmetic with trapping overflow
+- dev BitTwiddlingHacks __absvsi2  // abs(a)
+- dev BitTwiddlingHacks __absvdi2  // abs(a)
+- dev BitTwiddlingHacks __absvti2  // abs(a)
+- port llvm __negvsi2              // -a symbol-level compatibility: libgcc
+- port llvm __negvdi2              // -a unnecessary: unused in backends
+- port llvm __negvti2              // -a
+- TODO upstreaming __addvsi3..__mulvti3 after testing panics works
+- dev HackersDelight __addvsi3     // a + b
+- dev HackersDelight __addvdi3     // a + b
+- dev HackersDelight __addvti3     // a + b
+- dev HackersDelight __subvsi3     // a - b
+- dev HackersDelight __subvdi3     // a - b
+- dev HackersDelight __subvti3     // a - b
+- dev HackersDelight __mulvsi3     // a * b
+- dev HackersDelight __mulvdi3     // a * b
+- dev HackersDelight __mulvti3     // a * b
+
+#### Integer Arithmetic which returns if overflow (would be faster without pointer)
+- dev HackersDelight __addosi4     // a + b, overflow=>ov.*=1 else 0
+- dev HackersDelight __addodi4     // (completeness + performance, llvm does not use them)
+- dev HackersDelight __addoti4     //
+- dev HackersDelight __subosi4     // a - b, overflow=>ov.*=1 else 0
+- dev HackersDelight __subodi4     // (completeness + performance, llvm does not use them)
+- dev HackersDelight __suboti4     //
+- dev HackersDelight __mulosi4     // a * b, overflow=>ov.*=1 else 0
+- dev HackersDelight __mulodi4     // (required by llvm)
+- dev HackersDelight __muloti4     //
+
+## Float library routines
+
+#### Float Conversion
+- todo todo __extendsfdf2  // extend a f32 => f64
+- todo todo __extendsftf2  // extend a f32 => f128
+- dev  llvm __extendsfxf2  // extend a f32 => f80
+- todo todo __extenddftf2  // extend a f64 => f128
+- dev  llvm __extenddfxf2  // extend a f64 => f80
+- todo todo __truncdfsf2   // truncate a to narrower mode of return type, rounding towards zero
+- todo todo __trunctfdf2   //
+- todo todo __trunctfsf2   //
+- dev  llvm __truncxfsf2   //
+- dev  llvm __truncxfdf2   //
+- todo todo __fixsfsi      // convert a to i32, rounding towards zero
+- todo todo __fixdfsi      //
+- todo todo __fixtfsi      //
+- none none __fixxfsi      // missing
+- todo todo __fixsfdi      // convert a to i64, rounding towards zero
+- todo todo __fixdfdi      //
+- todo todo __fixtfdi      //
+- none none __fixxfdi      // missing
+- todo todo __fixsfti      // convert a to i128, rounding towards zero
+- todo todo __fixdfti      //
+- todo todo __fixtfdi      //
+- none none __fixxfti      // missing
+
+- __fixunssfsi   // convert to u32, rounding towards zero. negative values become 0.
+- __fixunsdfsi   //
+- __fixunstfsi   //
+- __fixunsxfsi   // missing
+- __fixunssfdi   // convert to u64, rounding towards zero. negative values become 0.
+- __fixunsdfdi   //
+- __fixunstfdi   //
+- __fixunsxfdi   // missing
+- __fixunssfti   // convert to u128, rounding towards zero. negative values become 0.
+- __fixunsdfti   //
+- __fixunstfdi   //
+- __fixunsxfti   // missing
+
+- __floatsisf    // convert i32 to floating point
+- __floatsidf    //
+- __floatsitf    //
+- __floatsixf    // missing
+- __floatdisf    // convert i64 to floating point
+- __floatdidf    //
+- __floatditf    //
+- __floatdixf    // missing
+- __floattisf    // convert i128 to floating point
+- __floattidf    //
+- __floattixf    // missing
+
+- __floatunsisf  // convert i32 to floating point
+- __floatunsidf  //
+- __floatunsitf  //
+- __floatunsixf  // missing
+- __floatundisf  // convert i64 to floating point
+- __floatundidf  //
+- __floatunditf  //
+- __floatundixf  // missing
+- __floatuntisf  // convert i128 to floating point
+- __floatuntidf  //
+- __floatuntitf  //
+- __floatuntixf  // missing
+
+#### Float Comparison
+- __cmpsf2       // return (a<b)=>-1,(a==b)=>0,(a>b)=>1,Nan=>1 dont rely on this
+- __cmpdf2       // exported from __lesf2, __ledf2, __letf2 (below)
+- __cmptf2       //
+- __unordsf2     // (input==NaN) => out!=0 else out=0,
+- __unorddf2     // __only reliable for (input!=Nan)__
+- __unordtf2     //
+- __eqsf2        // (a!=NaN) and (b!=Nan) and (a==b) => output=0
+- __eqdf2        //
+- __eqtf2        //
+- __nesf2        // (a==NaN) or (b==Nan) or (a!=b) => output!=0
+- __nedf2        //
+- __netf2        //
+- __gesf2        // (a!=Nan) and (b!=Nan) and (a>=b) => output>=0
+- __gedf2        //
+- __getf2        //
+- __ltsf2        // (a!=Nan) and (b!=Nan) and (a<b) => output<0
+- __ltdf2        //
+- __lttf2        //
+- __lesf2        // (a!=Nan) and (b!=Nan) and (a<=b) => output<=0
+- __ledf2        //
+- __letf2        //
+- __gtsf2        // (a!=Nan) and (b!=Nan) and (a>b) => output>0
+- __gtdf2        //
+- __gttf2        //
+
+#### Float Arithmetic
+- __addsf3       // a + b f32
+- __adddf3       // a + b f64
+- __addtf3       // a + b f128
+- __addxf3       // a + b f80
+- __aeabi_fadd   // a + b f64 ARM: AAPCS
+- __aeabi_dadd   // a + b f64 ARM: AAPCS
+- __subsf3       // a - b
+- __subdf3       // a - b
+- __subtf3       // a - b
+- __subxf3       // a - b f80
+- __aeabi_fsub   // a - b f64 ARM: AAPCS
+- __aeabi_dsub   // a - b f64 ARM: AAPCS
+- __mulsf3       // a * b
+- __muldf3       // a * b
+- __multf3       // a * b
+- __mulxf3       // a * b missing
+- __divsf3       // a / b
+- __divdf3       // a / b
+- __divtf3       // a / b
+- __divxf3       // a / b missing
+- __negsf2       // -a symbol-level compatibility: libgcc uses this for the rl78
+- __negdf2       // -a unnecessary: can be lowered directly to a xor
+- __negtf2       // -a
+- __negxf2       // -a
 
-Any bugs should be solved by trying to duplicate the bug upstream.
- * If the bug exists upstream, get it fixed with the LLVM team and then port
-   the fix downstream to Zig.
- * If the bug only exists in Zig, something went wrong porting the code,
-   and you can run the C code and Zig code side by side in a debugger
-   to figure out what's happening differently.
+#### Floating point raised to integer power
+- __powisf2  // unclear, if supported a ^ b
+- __powidf2  //
+- __powitf2  //
+- __powixf2  //
+- __mulsc3   // unsupported (a+ib) * (c+id)
+- __muldc3   //
+- __multc3   //
+- __mulxc3   //
+- __divsc3   // unsupported (a+ib) * / (c+id)
+- __divdc3   //
+- __divtc3   //
+- __divxc3   //
lib/std/special/compiler_rt/trunc_f80.zig
@@ -10,7 +10,7 @@ pub fn __truncxfhf2(a: f80) callconv(.C) F16T {
     return @bitCast(F16T, trunc(f16, a));
 }
 
-pub fn __truncxfff2(a: f80) callconv(.C) f32 {
+pub fn __truncxfsf2(a: f80) callconv(.C) f32 {
     return trunc(f32, a);
 }
 
lib/std/special/compiler_rt.zig
@@ -41,8 +41,8 @@ comptime {
 
     const __extendhfxf2 = @import("compiler_rt/extend_f80.zig").__extendhfxf2;
     @export(__extendhfxf2, .{ .name = "__extendhfxf2", .linkage = linkage });
-    const __extendffxf2 = @import("compiler_rt/extend_f80.zig").__extendffxf2;
-    @export(__extendffxf2, .{ .name = "__extendffxf2", .linkage = linkage });
+    const __extendsfxf2 = @import("compiler_rt/extend_f80.zig").__extendsfxf2;
+    @export(__extendsfxf2, .{ .name = "__extendsfxf2", .linkage = linkage });
     const __extenddfxf2 = @import("compiler_rt/extend_f80.zig").__extenddfxf2;
     @export(__extenddfxf2, .{ .name = "__extenddfxf2", .linkage = linkage });
     const __extendxftf2 = @import("compiler_rt/extend_f80.zig").__extendxftf2;
@@ -105,26 +105,6 @@ comptime {
         @export(__extendhfsf2, .{ .name = "__gnu_h2f_ieee", .linkage = linkage });
     }
 
-    // Integral arithmetic which returns if overflow
-    const __addosi4 = @import("compiler_rt/addo.zig").__addosi4;
-    @export(__addosi4, .{ .name = "__addosi4", .linkage = linkage });
-    const __addodi4 = @import("compiler_rt/addo.zig").__addodi4;
-    @export(__addodi4, .{ .name = "__addodi4", .linkage = linkage });
-    const __addoti4 = @import("compiler_rt/addo.zig").__addoti4;
-    @export(__addoti4, .{ .name = "__addoti4", .linkage = linkage });
-    const __subosi4 = @import("compiler_rt/subo.zig").__subosi4;
-    @export(__subosi4, .{ .name = "__subosi4", .linkage = linkage });
-    const __subodi4 = @import("compiler_rt/subo.zig").__subodi4;
-    @export(__subodi4, .{ .name = "__subodi4", .linkage = linkage });
-    const __suboti4 = @import("compiler_rt/subo.zig").__suboti4;
-    @export(__suboti4, .{ .name = "__suboti4", .linkage = linkage });
-    const __mulosi4 = @import("compiler_rt/mulo.zig").__mulosi4;
-    @export(__mulosi4, .{ .name = "__mulosi4", .linkage = linkage });
-    const __mulodi4 = @import("compiler_rt/mulo.zig").__mulodi4;
-    @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage });
-    const __muloti4 = @import("compiler_rt/mulo.zig").__muloti4;
-    @export(__muloti4, .{ .name = "__muloti4", .linkage = linkage });
-
     if (builtin.os.tag == .windows) {
         // Default stack-probe functions emitted by LLVM
         if (is_mingw) {
@@ -214,8 +194,8 @@ comptime {
 
     const __truncxfhf2 = @import("compiler_rt/trunc_f80.zig").__truncxfhf2;
     @export(__truncxfhf2, .{ .name = "__truncxfhf2", .linkage = linkage });
-    const __truncxfff2 = @import("compiler_rt/trunc_f80.zig").__truncxfff2;
-    @export(__truncxfff2, .{ .name = "__truncxfff2", .linkage = linkage });
+    const __truncxfsf2 = @import("compiler_rt/trunc_f80.zig").__truncxfsf2;
+    @export(__truncxfsf2, .{ .name = "__truncxfsf2", .linkage = linkage });
     const __truncxfdf2 = @import("compiler_rt/trunc_f80.zig").__truncxfdf2;
     @export(__truncxfdf2, .{ .name = "__truncxfdf2", .linkage = linkage });
     const __trunctfxf2 = @import("compiler_rt/trunc_f80.zig").__trunctfxf2;
@@ -274,20 +254,7 @@ comptime {
     const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3;
     @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage });
 
-    // Integral bit manipulation
-    const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3;
-    @export(__ashldi3, .{ .name = "__ashldi3", .linkage = linkage });
-    const __ashlti3 = @import("compiler_rt/shift.zig").__ashlti3;
-    @export(__ashlti3, .{ .name = "__ashlti3", .linkage = linkage });
-    const __ashrdi3 = @import("compiler_rt/shift.zig").__ashrdi3;
-    @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage });
-    const __ashrti3 = @import("compiler_rt/shift.zig").__ashrti3;
-    @export(__ashrti3, .{ .name = "__ashrti3", .linkage = linkage });
-    const __lshrdi3 = @import("compiler_rt/shift.zig").__lshrdi3;
-    @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage });
-    const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3;
-    @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });
-
+    // Integer Bit operations
     const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2;
     @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage });
     const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2;
@@ -306,21 +273,18 @@ comptime {
     @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = linkage });
     const __ffsti2 = @import("compiler_rt/count0bits.zig").__ffsti2;
     @export(__ffsti2, .{ .name = "__ffsti2", .linkage = linkage });
-
     const __paritysi2 = @import("compiler_rt/parity.zig").__paritysi2;
     @export(__paritysi2, .{ .name = "__paritysi2", .linkage = linkage });
     const __paritydi2 = @import("compiler_rt/parity.zig").__paritydi2;
     @export(__paritydi2, .{ .name = "__paritydi2", .linkage = linkage });
     const __parityti2 = @import("compiler_rt/parity.zig").__parityti2;
     @export(__parityti2, .{ .name = "__parityti2", .linkage = linkage });
-
     const __popcountsi2 = @import("compiler_rt/popcount.zig").__popcountsi2;
     @export(__popcountsi2, .{ .name = "__popcountsi2", .linkage = linkage });
     const __popcountdi2 = @import("compiler_rt/popcount.zig").__popcountdi2;
     @export(__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage });
     const __popcountti2 = @import("compiler_rt/popcount.zig").__popcountti2;
     @export(__popcountti2, .{ .name = "__popcountti2", .linkage = linkage });
-
     const __bswapsi2 = @import("compiler_rt/bswap.zig").__bswapsi2;
     @export(__bswapsi2, .{ .name = "__bswapsi2", .linkage = linkage });
     const __bswapdi2 = @import("compiler_rt/bswap.zig").__bswapdi2;
@@ -429,13 +393,26 @@ comptime {
         @export(__isPlatformVersionAtLeast, .{ .name = "__isPlatformVersionAtLeast", .linkage = linkage });
     }
 
-    // Integral arithmetic
+    // Integer Arithmetic
+    const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3;
+    @export(__ashldi3, .{ .name = "__ashldi3", .linkage = linkage });
+    const __ashlti3 = @import("compiler_rt/shift.zig").__ashlti3;
+    @export(__ashlti3, .{ .name = "__ashlti3", .linkage = linkage });
+    const __ashrdi3 = @import("compiler_rt/shift.zig").__ashrdi3;
+    @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage });
+    const __ashrti3 = @import("compiler_rt/shift.zig").__ashrti3;
+    @export(__ashrti3, .{ .name = "__ashrti3", .linkage = linkage });
+    const __lshrdi3 = @import("compiler_rt/shift.zig").__lshrdi3;
+    @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage });
+    const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3;
+    @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });
     const __negsi2 = @import("compiler_rt/negXi2.zig").__negsi2;
     @export(__negsi2, .{ .name = "__negsi2", .linkage = linkage });
     const __negdi2 = @import("compiler_rt/negXi2.zig").__negdi2;
     @export(__negdi2, .{ .name = "__negdi2", .linkage = linkage });
     const __negti2 = @import("compiler_rt/negXi2.zig").__negti2;
     @export(__negti2, .{ .name = "__negti2", .linkage = linkage });
+
     const __mulsi3 = @import("compiler_rt/int.zig").__mulsi3;
     @export(__mulsi3, .{ .name = "__mulsi3", .linkage = linkage });
     const __muldi3 = @import("compiler_rt/muldi3.zig").__muldi3;
@@ -463,7 +440,7 @@ comptime {
     const __udivmodsi4 = @import("compiler_rt/int.zig").__udivmodsi4;
     @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = linkage });
 
-    // Integral arithmetic with trapping overflow
+    // Integer Arithmetic with trapping overflow
     const __absvsi2 = @import("compiler_rt/absv.zig").__absvsi2;
     @export(__absvsi2, .{ .name = "__absvsi2", .linkage = linkage });
     const __absvdi2 = @import("compiler_rt/absv.zig").__absvdi2;
@@ -477,9 +454,27 @@ comptime {
     const __negvti2 = @import("compiler_rt/negv.zig").__negvti2;
     @export(__negvti2, .{ .name = "__negvti2", .linkage = linkage });
 
-    // missing: Integral arithmetic which returns if overflow
+    // Integer arithmetic which returns if overflow
+    const __addosi4 = @import("compiler_rt/addo.zig").__addosi4;
+    @export(__addosi4, .{ .name = "__addosi4", .linkage = linkage });
+    const __addodi4 = @import("compiler_rt/addo.zig").__addodi4;
+    @export(__addodi4, .{ .name = "__addodi4", .linkage = linkage });
+    const __addoti4 = @import("compiler_rt/addo.zig").__addoti4;
+    @export(__addoti4, .{ .name = "__addoti4", .linkage = linkage });
+    const __subosi4 = @import("compiler_rt/subo.zig").__subosi4;
+    @export(__subosi4, .{ .name = "__subosi4", .linkage = linkage });
+    const __subodi4 = @import("compiler_rt/subo.zig").__subodi4;
+    @export(__subodi4, .{ .name = "__subodi4", .linkage = linkage });
+    const __suboti4 = @import("compiler_rt/subo.zig").__suboti4;
+    @export(__suboti4, .{ .name = "__suboti4", .linkage = linkage });
+    const __mulosi4 = @import("compiler_rt/mulo.zig").__mulosi4;
+    @export(__mulosi4, .{ .name = "__mulosi4", .linkage = linkage });
+    const __mulodi4 = @import("compiler_rt/mulo.zig").__mulodi4;
+    @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage });
+    const __muloti4 = @import("compiler_rt/mulo.zig").__muloti4;
+    @export(__muloti4, .{ .name = "__muloti4", .linkage = linkage });
 
-    // Integral comparison
+    // Integer Comparison
     // (a <  b) => 0
     // (a == b) => 1
     // (a >  b) => 2
src/stage1/codegen.cpp
@@ -1641,7 +1641,7 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty
                 break;
             case 32:
                 return_type = g->builtin_types.entry_f32->llvm_type;
-                func_name = "__truncxfff2";
+                func_name = "__truncxfsf2";
                 break;
             case 64:
                 return_type = g->builtin_types.entry_f64->llvm_type;
@@ -1670,7 +1670,7 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty
                 break;
             case 32:
                 param_type = g->builtin_types.entry_f32->llvm_type;
-                func_name = "__extendffxf2";
+                func_name = "__extendsfxf2";
                 break;
             case 64:
                 param_type = g->builtin_types.entry_f64->llvm_type;