From f0da2c055a4a003f70a7da73d91c546930b4586d Mon Sep 17 00:00:00 2001 From: Colin Ford Date: Tue, 20 Oct 2026 19:10:32 -0700 Subject: [PATCH 1/5] Assemble x86_64 kernels for Mach-O The x86-64 .s kernels used ELF-only directives, so the library did not build on Intel Macs. Select Mach-O directives with .ifdef BEMAN_BIG_INT_MACHO, defined by CMake for Apple targets. ELF output is unchanged. --- CMakeLists.txt | 7 + ...multiply_long_runtime_x86_64_avx512_ifma.s | 29 ++- src/multiply_long_runtime_x86_64_bmi2_adx.s | 43 ++-- src/multiply_long_runtime_x86_64_generic.s | 63 +++-- src/square_long_runtime_x86_64_avx512_ifma.s | 35 ++- src/square_long_runtime_x86_64_bmi2_adx.s | 223 ++++++++++-------- src/square_long_runtime_x86_64_generic.s | 69 +++--- 7 files changed, 289 insertions(+), 180 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 594a5287..c9af70e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,6 +205,13 @@ if( src/square_long_runtime_x86_64_avx512_ifma.s ) set(_bigint_x86_64_kernels TRUE) + # The .s kernels select their Mach-O directives with .ifdef on this symbol + if(APPLE) + target_compile_options( + beman.big_int + PRIVATE $<$:-Wa,--defsym,BEMAN_BIG_INT_MACHO=1> + ) + endif() elseif( ( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" diff --git a/src/multiply_long_runtime_x86_64_avx512_ifma.s b/src/multiply_long_runtime_x86_64_avx512_ifma.s index f18568a5..add33383 100644 --- a/src/multiply_long_runtime_x86_64_avx512_ifma.s +++ b/src/multiply_long_runtime_x86_64_avx512_ifma.s @@ -5,7 +5,9 @@ .altmacro # Empty, but present, GNU-stack section +.ifndef BEMAN_BIG_INT_MACHO .section .note.GNU-stack,"",%progbits +.endif # --------------------------------------------------------------------------- # AVX-512 IFMA (radix 2^52) schoolbook multiply. Contract matches @@ -83,29 +85,33 @@ .set FRAME_SIZE_RAW, FRAME_SCRATCH_OFF + 120 .set FRAME_SIZE, ((FRAME_SIZE_RAW + 63) & ~63) +.ifdef BEMAN_BIG_INT_MACHO +.section __TEXT,__const +.else .section .rodata -.align 64 +.endif +.balign 64 Lidx_unpack: .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d .byte 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a .byte 0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 .byte 0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34 -.align 64 +.balign 64 Lshift_common: .quad 0,4,0,4,0,4,0,4 -.align 64 +.balign 64 Lidx_pack_a: .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x10,0x11,0x12 .byte 0x13,0x14,0x15,0x16,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x20,0x21,0x22,0x23,0x24,0x25 .byte 0x26,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x39,0x3a .byte 0x3b,0x3c,0x3d,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -.align 64 +.balign 64 Lidx_pack_b: .byte 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x08,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f .byte 0x3f,0x3f,0x3f,0x18,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f .byte 0x28,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x38,0x3f,0x3f .byte 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f -.align 64 +.balign 64 Lm52_bcst: .quad 0xFFFFFFFFFFFFF Lone_bcst: @@ -113,7 +119,11 @@ Lone_bcst: Lseven_bcst: .quad 7 +.ifdef BEMAN_BIG_INT_MACHO +.text +.else .section .text +.endif # Masked 64-byte group load helper. In: rax=signed byte offset (relative to # a source base), rdx=source total byte length. Out: k1 = load mask @@ -145,8 +155,15 @@ Lseven_bcst: kmovq k1, rcx .endm +.ifdef BEMAN_BIG_INT_MACHO +.globl _beman_big_int_multiply_long_runtime_avx512_ifma +.else .globl beman_big_int_multiply_long_runtime_avx512_ifma .type beman_big_int_multiply_long_runtime_avx512_ifma, @function +.endif +.ifdef BEMAN_BIG_INT_MACHO +_beman_big_int_multiply_long_runtime_avx512_ifma: +.endif beman_big_int_multiply_long_runtime_avx512_ifma: .cfi_startproc test rdx, rdx @@ -557,4 +574,6 @@ Lbchunk_done: Lret_noop: ret .cfi_endproc +.ifndef BEMAN_BIG_INT_MACHO .size beman_big_int_multiply_long_runtime_avx512_ifma, .-beman_big_int_multiply_long_runtime_avx512_ifma +.endif diff --git a/src/multiply_long_runtime_x86_64_bmi2_adx.s b/src/multiply_long_runtime_x86_64_bmi2_adx.s index 591e6e6b..0d42e195 100644 --- a/src/multiply_long_runtime_x86_64_bmi2_adx.s +++ b/src/multiply_long_runtime_x86_64_bmi2_adx.s @@ -9,10 +9,16 @@ # as "x - (x/2)*2" throughout instead. # Empty, but present, GNU-stack section +.ifndef BEMAN_BIG_INT_MACHO .section .note.GNU-stack,"",%progbits +.endif # Enter the text section for code/symbols +.ifdef BEMAN_BIG_INT_MACHO +.text +.else .section .text +.endif # Schoolbook long multiplication, x86-64 with BMI2 (mulx) and ADX (adcx/adox). # Contract matches beman_big_int_multiply_long_runtime (see @@ -49,35 +55,39 @@ .set BLOCK, 16 .set LOG2_BLOCK, 4 +.ifdef BEMAN_BIG_INT_MACHO +.globl _beman_big_int_multiply_long_runtime_bmi2_adx +.else .globl beman_big_int_multiply_long_runtime_bmi2_adx .type beman_big_int_multiply_long_runtime_bmi2_adx, @function +.endif # Core per-limb macros, shared by both tiers. .macro MULSLOT off, hi, lo, hiprev - mulx hi, lo, QWORD PTR [rsi + off] - adcx lo, hiprev - mov QWORD PTR [rdi + off], lo + mulx \hi, \lo, QWORD PTR [rsi + \off] + adcx \lo, \hiprev + mov QWORD PTR [rdi + \off], \lo .endm .macro ADDMULSLOT off, hi, lo, hiprev, scratch - mulx hi, lo, QWORD PTR [rsi + off] - mov scratch, QWORD PTR [rdi + off] - adcx lo, hiprev - adox lo, scratch - mov QWORD PTR [rdi + off], lo + mulx \hi, \lo, QWORD PTR [rsi + \off] + mov \scratch, QWORD PTR [rdi + \off] + adcx \lo, \hiprev + adox \lo, \scratch + mov QWORD PTR [rdi + \off], \lo .endm .macro MULSLOT0 off, hi, lo - mulx hi, lo, QWORD PTR [rsi + off] - mov QWORD PTR [rdi + off], lo + mulx \hi, \lo, QWORD PTR [rsi + \off] + mov QWORD PTR [rdi + \off], \lo .endm .macro ADDMULSLOT0 off, hi, lo, scratch - mulx hi, lo, QWORD PTR [rsi + off] - mov scratch, QWORD PTR [rdi + off] - adox lo, scratch - mov QWORD PTR [rdi + off], lo + mulx \hi, \lo, QWORD PTR [rsi + \off] + mov \scratch, QWORD PTR [rdi + \off] + adox \lo, \scratch + mov QWORD PTR [rdi + \off], \lo .endm # Exact-length tier: len_a in [1, LA_EXACT_MAX]. @@ -292,6 +302,9 @@ Lgen_rem_addmul\r: .long Lgen_rem_addmul\r - Lgen_addmul_table .endm +.ifdef BEMAN_BIG_INT_MACHO +_beman_big_int_multiply_long_runtime_bmi2_adx: +.endif beman_big_int_multiply_long_runtime_bmi2_adx: .cfi_startproc @@ -468,4 +481,6 @@ Lend_short: ret .cfi_endproc +.ifndef BEMAN_BIG_INT_MACHO .size beman_big_int_multiply_long_runtime_bmi2_adx, .-beman_big_int_multiply_long_runtime_bmi2_adx +.endif diff --git a/src/multiply_long_runtime_x86_64_generic.s b/src/multiply_long_runtime_x86_64_generic.s index 2122671b..6a93ded8 100644 --- a/src/multiply_long_runtime_x86_64_generic.s +++ b/src/multiply_long_runtime_x86_64_generic.s @@ -4,15 +4,25 @@ .intel_syntax noprefix # Empty, but present, GNU-stack section +.ifndef BEMAN_BIG_INT_MACHO .section .note.GNU-stack,"",%progbits +.endif # Enter the text section for code/symbols +.ifdef BEMAN_BIG_INT_MACHO +.text +.else .section .text +.endif # Schoolbook long multiplication, baseline x86-64 only (no SSE/AVX, no BMI2/ADX). +.ifdef BEMAN_BIG_INT_MACHO +.globl _beman_big_int_multiply_long_runtime_generic +.else .globl beman_big_int_multiply_long_runtime_generic .type beman_big_int_multiply_long_runtime_generic, @function +.endif # rdi -> p_result # rsi -> p_a @@ -74,6 +84,9 @@ .endm +.ifdef BEMAN_BIG_INT_MACHO +_beman_big_int_multiply_long_runtime_generic: +.endif beman_big_int_multiply_long_runtime_generic: .cfi_startproc @@ -85,21 +98,21 @@ beman_big_int_multiply_long_runtime_generic: .cfi_adjust_cfa_offset 8 .cfi_rel_offset r12, 0 -.Lgeneric_x64_start: +Lgeneric_x64_start: # a * b is symmetric, so run the inner loop over the longer operand: that # makes the number of rows, and with it all per-row overhead, min(len_a, len_b). cmp rdx, r8 - jae .Lgeneric_x64_sizes_ordered + jae Lgeneric_x64_sizes_ordered xchg rsi, rcx xchg rdx, r8 -.Lgeneric_x64_sizes_ordered: +Lgeneric_x64_sizes_ordered: test r8, r8 # an empty operand leaves nothing to do - jz .Lgeneric_x64_end + jz Lgeneric_x64_end mov r9, rdx # free up rdx for the mul instruction @@ -122,23 +135,23 @@ beman_big_int_multiply_long_runtime_generic: xor r11d, r11d # temp = 0 cmp rbx, r12 - je .Lgeneric_x64_mul_row_4x + je Lgeneric_x64_mul_row_4x -.Lgeneric_x64_mul_row_rmdr: +Lgeneric_x64_mul_row_rmdr: GENERIC_X64_MUL_LIMB 0 add rbx, 1 # i++ cmp rbx, r12 - jne .Lgeneric_x64_mul_row_rmdr # if (i != -(len_a & ~3)) { goto rmdr_loop_start; } + jne Lgeneric_x64_mul_row_rmdr # if (i != -(len_a & ~3)) { goto rmdr_loop_start; } -.Lgeneric_x64_mul_row_4x: +Lgeneric_x64_mul_row_4x: test rbx, rbx - jz .Lgeneric_x64_mul_row_end + jz Lgeneric_x64_mul_row_end .p2align 4 -.Lgeneric_x64_mul_row_4x_unroll: +Lgeneric_x64_mul_row_4x_unroll: GENERIC_X64_MUL_LIMB 0 GENERIC_X64_MUL_LIMB 8 @@ -146,42 +159,42 @@ beman_big_int_multiply_long_runtime_generic: GENERIC_X64_MUL_LIMB 24 add rbx, 4 # i += 4 - jnz .Lgeneric_x64_mul_row_4x_unroll # if (i != 0) { goto unroll_loop_start; } + jnz Lgeneric_x64_mul_row_4x_unroll # if (i != 0) { goto unroll_loop_start; } -.Lgeneric_x64_mul_row_end: +Lgeneric_x64_mul_row_end: mov QWORD PTR [rdi], r11 # result[len_a] = temp add rdi, 8 # increment the result ptr for next iter add rcx, 8 # increment the b ptr for next iter sub r8, 1 # len_b-- - jz .Lgeneric_x64_end + jz Lgeneric_x64_end .p2align 4 -.Lgeneric_x64_outer_loop_start: +Lgeneric_x64_outer_loop_start: mov r10, QWORD PTR [rcx] # r10 = b[j] mov rbx, r9 # i = -len_a xor r11d, r11d # temp = 0 cmp rbx, r12 - je .Lgeneric_x64_inner_loop_4x + je Lgeneric_x64_inner_loop_4x -.Lgeneric_x64_inner_loop_rmdr: +Lgeneric_x64_inner_loop_rmdr: GENERIC_X64_ADDMUL_LIMB 0 add rbx, 1 # i++ cmp rbx, r12 - jne .Lgeneric_x64_inner_loop_rmdr # if (i != -(len_a & ~3)) { goto rmdr_loop_start; } + jne Lgeneric_x64_inner_loop_rmdr # if (i != -(len_a & ~3)) { goto rmdr_loop_start; } -.Lgeneric_x64_inner_loop_4x: +Lgeneric_x64_inner_loop_4x: test rbx, rbx - jz .Lgeneric_x64_outer_loop_end + jz Lgeneric_x64_outer_loop_end .p2align 4 -.Lgeneric_x64_inner_loop_4x_unroll: +Lgeneric_x64_inner_loop_4x_unroll: GENERIC_X64_ADDMUL_LIMB 0 GENERIC_X64_ADDMUL_LIMB 8 @@ -189,18 +202,18 @@ beman_big_int_multiply_long_runtime_generic: GENERIC_X64_ADDMUL_LIMB 24 add rbx, 4 # i += 4 - jnz .Lgeneric_x64_inner_loop_4x_unroll # if (i != 0) { goto unroll_loop_start; } + jnz Lgeneric_x64_inner_loop_4x_unroll # if (i != 0) { goto unroll_loop_start; } -.Lgeneric_x64_outer_loop_end: +Lgeneric_x64_outer_loop_end: mov QWORD PTR [rdi], r11 # result[len_a + j] = temp add rdi, 8 # increment the result ptr for next iter add rcx, 8 # increment the b ptr for next iter sub r8, 1 # len_b-- - jnz .Lgeneric_x64_outer_loop_start # if (len_b != 0) { goto outer_loop_start; } + jnz Lgeneric_x64_outer_loop_start # if (len_b != 0) { goto outer_loop_start; } -.Lgeneric_x64_end: +Lgeneric_x64_end: pop r12 .cfi_adjust_cfa_offset -8 @@ -210,4 +223,6 @@ beman_big_int_multiply_long_runtime_generic: ret .cfi_endproc +.ifndef BEMAN_BIG_INT_MACHO .size beman_big_int_multiply_long_runtime_generic, .-beman_big_int_multiply_long_runtime_generic +.endif diff --git a/src/square_long_runtime_x86_64_avx512_ifma.s b/src/square_long_runtime_x86_64_avx512_ifma.s index 0a8b5528..807fdee9 100644 --- a/src/square_long_runtime_x86_64_avx512_ifma.s +++ b/src/square_long_runtime_x86_64_avx512_ifma.s @@ -4,7 +4,9 @@ .intel_syntax noprefix .altmacro +.ifndef BEMAN_BIG_INT_MACHO .section .note.GNU-stack,"",%progbits +.endif # --------------------------------------------------------------------------- # AVX-512 IFMA (radix 2^52) schoolbook squaring. Contract matches @@ -70,40 +72,48 @@ .set FRAME_SIZE_RAW, FRAME_SCRATCH_OFF + 40 .set FRAME_SIZE, ((FRAME_SIZE_RAW + 63) & ~63) +.ifdef BEMAN_BIG_INT_MACHO +.section __TEXT,__const +.else .section .rodata -.align 64 +.endif +.balign 64 LSidx_unpack: .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d .byte 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a .byte 0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 .byte 0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34 -.align 64 +.balign 64 LSshift_common: .quad 0,4,0,4,0,4,0,4 -.align 64 +.balign 64 LSidx_pack_a: .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x10,0x11,0x12 .byte 0x13,0x14,0x15,0x16,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x20,0x21,0x22,0x23,0x24,0x25 .byte 0x26,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x39,0x3a .byte 0x3b,0x3c,0x3d,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -.align 64 +.balign 64 LSidx_pack_b: .byte 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x08,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f .byte 0x3f,0x3f,0x3f,0x18,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f .byte 0x28,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x38,0x3f,0x3f .byte 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f -.align 64 +.balign 64 LSm52_bcst: .quad 0xFFFFFFFFFFFFF LSone_bcst: .quad 1 LSseven_bcst: .quad 7 -.align 64 +.balign 64 LSdup_idx: .quad 0,0,1,1,2,2,3,3 +.ifdef BEMAN_BIG_INT_MACHO +.text +.else .section .text +.endif # Masked 64-byte group load helper (identical to the multiply kernel's). # In: rax=signed byte offset, rdx=source total byte length. @@ -132,8 +142,15 @@ LSdup_idx: kmovq k1, rcx .endm +.ifdef BEMAN_BIG_INT_MACHO +.globl _beman_big_int_square_long_runtime_avx512_ifma +.else .globl beman_big_int_square_long_runtime_avx512_ifma .type beman_big_int_square_long_runtime_avx512_ifma, @function +.endif +.ifdef BEMAN_BIG_INT_MACHO +_beman_big_int_square_long_runtime_avx512_ifma: +.endif beman_big_int_square_long_runtime_avx512_ifma: .cfi_startproc test rdx, rdx @@ -447,6 +464,12 @@ LSblock_done: LSret_noop: ret LStail_jump: +.ifdef BEMAN_BIG_INT_MACHO + jmp _beman_big_int_square_long_runtime_bmi2_adx +.else jmp beman_big_int_square_long_runtime_bmi2_adx@PLT +.endif .cfi_endproc +.ifndef BEMAN_BIG_INT_MACHO .size beman_big_int_square_long_runtime_avx512_ifma, .-beman_big_int_square_long_runtime_avx512_ifma +.endif diff --git a/src/square_long_runtime_x86_64_bmi2_adx.s b/src/square_long_runtime_x86_64_bmi2_adx.s index 9aa94a94..b917fb4c 100644 --- a/src/square_long_runtime_x86_64_bmi2_adx.s +++ b/src/square_long_runtime_x86_64_bmi2_adx.s @@ -4,15 +4,25 @@ .intel_syntax noprefix # Empty, but present, GNU-stack section +.ifndef BEMAN_BIG_INT_MACHO .section .note.GNU-stack,"",%progbits +.endif # Enter the text section for code/symbols +.ifdef BEMAN_BIG_INT_MACHO +.text +.else .section .text +.endif # Schoolbook squaring, x86-64 with BMI2 (mulx) and ADX (adcx/adox). +.ifdef BEMAN_BIG_INT_MACHO +.globl _beman_big_int_square_long_runtime_bmi2_adx +.else .globl beman_big_int_square_long_runtime_bmi2_adx .type beman_big_int_square_long_runtime_bmi2_adx, @function +.endif # rdi -> p_result # rsi -> p_a @@ -91,7 +101,7 @@ lea rcx, [r8 + BLOCK - 1] shr rcx, LOG2_BLOCK # rcx = trip_count = ceil(row_len / BLOCK) - lea r10, [rip + .Lentry_table_\tag] + lea r10, [rip + Lentry_table_\tag] movsxd rax, DWORD PTR [r10 + rax * 4] add r10, rax # r10 = jump target address @@ -143,6 +153,9 @@ .set BLOCK, 16 .set LOG2_BLOCK, 4 +.ifdef BEMAN_BIG_INT_MACHO +_beman_big_int_square_long_runtime_bmi2_adx: +.endif beman_big_int_square_long_runtime_bmi2_adx: .cfi_startproc @@ -167,7 +180,7 @@ beman_big_int_square_long_runtime_bmi2_adx: .cfi_rel_offset r15, 0 cmp rdx, 1 - jbe .Lbmi2_sqr_tiny # with at most one limb there is no triangle + jbe Lbmi2_sqr_tiny # with at most one limb there is no triangle mov r9, rdx # rdx currently = len_a @@ -187,11 +200,11 @@ beman_big_int_square_long_runtime_bmi2_adx: DIAG_ROW0 cmp r8, 1 - je .Lrow0_len1 + je Lrow0_len1 cmp r8, 2 - je .Lrow0_len2 + je Lrow0_len2 cmp r8, 3 - je .Lrow0_len3 + je Lrow0_len3 ROW_SETUP row0 @@ -200,23 +213,23 @@ beman_big_int_square_long_runtime_bmi2_adx: mov r11, r15 # carry-in seed = prev_seed (read by an odd entry slot) jmp r10 # Duff's-device entry -.Lrow0_len1: +Lrow0_len1: ROW_SETUP_SIMPLE xor eax, eax mov r13, r15 MSLOT 0, r10, r11, r13 mov r13, r11 # the row-end code below expects the carry in r13 - jmp .Lrow0_done + jmp Lrow0_done -.Lrow0_len2: +Lrow0_len2: ROW_SETUP_SIMPLE xor eax, eax mov r13, r15 MSLOT 0, r10, r11, r13 MSLOT 8, r12, r13, r11 - jmp .Lrow0_done + jmp Lrow0_done -.Lrow0_len3: +Lrow0_len3: ROW_SETUP_SIMPLE xor eax, eax mov r13, r15 @@ -224,67 +237,67 @@ beman_big_int_square_long_runtime_bmi2_adx: MSLOT 8, r12, r13, r11 MSLOT 16, r10, r11, r13 mov r13, r11 - jmp .Lrow0_done - -.Lentry_table_row0: - .long .Lrow0_slot0 - .Lentry_table_row0 - .long .Lrow0_slot1 - .Lentry_table_row0 - .long .Lrow0_slot2 - .Lentry_table_row0 - .long .Lrow0_slot3 - .Lentry_table_row0 - .long .Lrow0_slot4 - .Lentry_table_row0 - .long .Lrow0_slot5 - .Lentry_table_row0 - .long .Lrow0_slot6 - .Lentry_table_row0 - .long .Lrow0_slot7 - .Lentry_table_row0 - .long .Lrow0_slot8 - .Lentry_table_row0 - .long .Lrow0_slot9 - .Lentry_table_row0 - .long .Lrow0_slot10 - .Lentry_table_row0 - .long .Lrow0_slot11 - .Lentry_table_row0 - .long .Lrow0_slot12 - .Lentry_table_row0 - .long .Lrow0_slot13 - .Lentry_table_row0 - .long .Lrow0_slot14 - .Lentry_table_row0 - .long .Lrow0_slot15 - .Lentry_table_row0 + jmp Lrow0_done + +Lentry_table_row0: + .long Lrow0_slot0 - Lentry_table_row0 + .long Lrow0_slot1 - Lentry_table_row0 + .long Lrow0_slot2 - Lentry_table_row0 + .long Lrow0_slot3 - Lentry_table_row0 + .long Lrow0_slot4 - Lentry_table_row0 + .long Lrow0_slot5 - Lentry_table_row0 + .long Lrow0_slot6 - Lentry_table_row0 + .long Lrow0_slot7 - Lentry_table_row0 + .long Lrow0_slot8 - Lentry_table_row0 + .long Lrow0_slot9 - Lentry_table_row0 + .long Lrow0_slot10 - Lentry_table_row0 + .long Lrow0_slot11 - Lentry_table_row0 + .long Lrow0_slot12 - Lentry_table_row0 + .long Lrow0_slot13 - Lentry_table_row0 + .long Lrow0_slot14 - Lentry_table_row0 + .long Lrow0_slot15 - Lentry_table_row0 .p2align 4 -.Lrow0_body: -.Lrow0_slot0: +Lrow0_body: +Lrow0_slot0: MSLOT 0, r10, r11, r13 -.Lrow0_slot1: +Lrow0_slot1: MSLOT 8, r12, r13, r11 -.Lrow0_slot2: +Lrow0_slot2: MSLOT 16, r10, r11, r13 -.Lrow0_slot3: +Lrow0_slot3: MSLOT 24, r12, r13, r11 -.Lrow0_slot4: +Lrow0_slot4: MSLOT 32, r10, r11, r13 -.Lrow0_slot5: +Lrow0_slot5: MSLOT 40, r12, r13, r11 -.Lrow0_slot6: +Lrow0_slot6: MSLOT 48, r10, r11, r13 -.Lrow0_slot7: +Lrow0_slot7: MSLOT 56, r12, r13, r11 -.Lrow0_slot8: +Lrow0_slot8: MSLOT 64, r10, r11, r13 -.Lrow0_slot9: +Lrow0_slot9: MSLOT 72, r12, r13, r11 -.Lrow0_slot10: +Lrow0_slot10: MSLOT 80, r10, r11, r13 -.Lrow0_slot11: +Lrow0_slot11: MSLOT 88, r12, r13, r11 -.Lrow0_slot12: +Lrow0_slot12: MSLOT 96, r10, r11, r13 -.Lrow0_slot13: +Lrow0_slot13: MSLOT 104, r12, r13, r11 -.Lrow0_slot14: +Lrow0_slot14: MSLOT 112, r10, r11, r13 -.Lrow0_slot15: +Lrow0_slot15: MSLOT 120, r12, r13, r11 lea rbx, [rbx + BLOCK * 8] lea r14, [r14 + BLOCK * 8] lea rcx, [rcx - 1] - jrcxz .Lrow0_done - jmp .Lrow0_body -.Lrow0_done: + jrcxz Lrow0_done + jmp Lrow0_body +Lrow0_done: adcx r13, rax # r13 += CF adox r13, rax # r13 += OF (r13 + CF + OF <= 2^64 - 1) @@ -292,10 +305,10 @@ beman_big_int_square_long_runtime_bmi2_adx: add rdi, 8 # increment the result ptr for next iter sub r8, 1 # row_len-- - jz .Lbmi2_sqr_diag # len_a == 2: the triangle is a single limb + jz Lbmi2_sqr_diag # len_a == 2: the triangle is a single limb .p2align 4 -.Lbmi2_sqr_outer_loop_start: +Lbmi2_sqr_outer_loop_start: mov r10, r8 neg r10 # r10 = true_index = -row_len @@ -303,11 +316,11 @@ beman_big_int_square_long_runtime_bmi2_adx: DIAG_OUTER cmp r8, 1 - je .Louter_len1 + je Louter_len1 cmp r8, 2 - je .Louter_len2 + je Louter_len2 cmp r8, 3 - je .Louter_len3 + je Louter_len3 ROW_SETUP outer @@ -316,23 +329,23 @@ beman_big_int_square_long_runtime_bmi2_adx: mov r11, r15 jmp r10 -.Louter_len1: +Louter_len1: ROW_SETUP_SIMPLE xor eax, eax mov r13, r15 ASLOT 0, r10, r11, r13, r12 mov r13, r11 # the row-end code below expects the carry in r13 - jmp .Louter_done + jmp Louter_done -.Louter_len2: +Louter_len2: ROW_SETUP_SIMPLE xor eax, eax mov r13, r15 ASLOT 0, r10, r11, r13, r12 ASLOT 8, r12, r13, r11, r10 - jmp .Louter_done + jmp Louter_done -.Louter_len3: +Louter_len3: ROW_SETUP_SIMPLE xor eax, eax mov r13, r15 @@ -340,67 +353,67 @@ beman_big_int_square_long_runtime_bmi2_adx: ASLOT 8, r12, r13, r11, r10 ASLOT 16, r10, r11, r13, r12 mov r13, r11 - jmp .Louter_done - -.Lentry_table_outer: - .long .Louter_slot0 - .Lentry_table_outer - .long .Louter_slot1 - .Lentry_table_outer - .long .Louter_slot2 - .Lentry_table_outer - .long .Louter_slot3 - .Lentry_table_outer - .long .Louter_slot4 - .Lentry_table_outer - .long .Louter_slot5 - .Lentry_table_outer - .long .Louter_slot6 - .Lentry_table_outer - .long .Louter_slot7 - .Lentry_table_outer - .long .Louter_slot8 - .Lentry_table_outer - .long .Louter_slot9 - .Lentry_table_outer - .long .Louter_slot10 - .Lentry_table_outer - .long .Louter_slot11 - .Lentry_table_outer - .long .Louter_slot12 - .Lentry_table_outer - .long .Louter_slot13 - .Lentry_table_outer - .long .Louter_slot14 - .Lentry_table_outer - .long .Louter_slot15 - .Lentry_table_outer + jmp Louter_done + +Lentry_table_outer: + .long Louter_slot0 - Lentry_table_outer + .long Louter_slot1 - Lentry_table_outer + .long Louter_slot2 - Lentry_table_outer + .long Louter_slot3 - Lentry_table_outer + .long Louter_slot4 - Lentry_table_outer + .long Louter_slot5 - Lentry_table_outer + .long Louter_slot6 - Lentry_table_outer + .long Louter_slot7 - Lentry_table_outer + .long Louter_slot8 - Lentry_table_outer + .long Louter_slot9 - Lentry_table_outer + .long Louter_slot10 - Lentry_table_outer + .long Louter_slot11 - Lentry_table_outer + .long Louter_slot12 - Lentry_table_outer + .long Louter_slot13 - Lentry_table_outer + .long Louter_slot14 - Lentry_table_outer + .long Louter_slot15 - Lentry_table_outer .p2align 4 -.Louter_body: -.Louter_slot0: +Louter_body: +Louter_slot0: ASLOT 0, r10, r11, r13, r12 -.Louter_slot1: +Louter_slot1: ASLOT 8, r12, r13, r11, r10 -.Louter_slot2: +Louter_slot2: ASLOT 16, r10, r11, r13, r12 -.Louter_slot3: +Louter_slot3: ASLOT 24, r12, r13, r11, r10 -.Louter_slot4: +Louter_slot4: ASLOT 32, r10, r11, r13, r12 -.Louter_slot5: +Louter_slot5: ASLOT 40, r12, r13, r11, r10 -.Louter_slot6: +Louter_slot6: ASLOT 48, r10, r11, r13, r12 -.Louter_slot7: +Louter_slot7: ASLOT 56, r12, r13, r11, r10 -.Louter_slot8: +Louter_slot8: ASLOT 64, r10, r11, r13, r12 -.Louter_slot9: +Louter_slot9: ASLOT 72, r12, r13, r11, r10 -.Louter_slot10: +Louter_slot10: ASLOT 80, r10, r11, r13, r12 -.Louter_slot11: +Louter_slot11: ASLOT 88, r12, r13, r11, r10 -.Louter_slot12: +Louter_slot12: ASLOT 96, r10, r11, r13, r12 -.Louter_slot13: +Louter_slot13: ASLOT 104, r12, r13, r11, r10 -.Louter_slot14: +Louter_slot14: ASLOT 112, r10, r11, r13, r12 -.Louter_slot15: +Louter_slot15: ASLOT 120, r12, r13, r11, r10 lea rbx, [rbx + BLOCK * 8] lea r14, [r14 + BLOCK * 8] lea rcx, [rcx - 1] - jrcxz .Louter_done - jmp .Louter_body -.Louter_done: + jrcxz Louter_done + jmp Louter_body +Louter_done: adcx r13, rax adox r13, rax @@ -408,9 +421,9 @@ beman_big_int_square_long_runtime_bmi2_adx: add rdi, 8 # increment the result ptr for next iter sub r8, 1 # row_len-- - jnz .Lbmi2_sqr_outer_loop_start # if (row_len != 0) { goto outer_loop_start; } + jnz Lbmi2_sqr_outer_loop_start # if (row_len != 0) { goto outer_loop_start; } -.Lbmi2_sqr_diag: +Lbmi2_sqr_diag: # Every row's own diagonal term was folded in at its own start # (DIAG_ROW0/DIAG_OUTER); only the last row's remains, landing on @@ -438,19 +451,19 @@ beman_big_int_square_long_runtime_bmi2_adx: adc r13, 0 # result[2n - 1] (no further carry: a^2 < B^(2 * len_a)) mov QWORD PTR [rdi], r13 - jmp .Lbmi2_sqr_end + jmp Lbmi2_sqr_end -.Lbmi2_sqr_tiny: +Lbmi2_sqr_tiny: test rdx, rdx # an empty operand leaves nothing to do - jz .Lbmi2_sqr_end + jz Lbmi2_sqr_end mov rdx, QWORD PTR [rsi] # rdx = a[0] mulx rcx, rax, rdx # rcx : rax = a[0]^2 (hi : lo) mov QWORD PTR [rdi], rax # result[0] = low64 mov QWORD PTR [rdi + 8], rcx # result[1] = high64 -.Lbmi2_sqr_end: +Lbmi2_sqr_end: pop r15 .cfi_adjust_cfa_offset -8 @@ -465,4 +478,6 @@ beman_big_int_square_long_runtime_bmi2_adx: ret .cfi_endproc +.ifndef BEMAN_BIG_INT_MACHO .size beman_big_int_square_long_runtime_bmi2_adx, .-beman_big_int_square_long_runtime_bmi2_adx +.endif diff --git a/src/square_long_runtime_x86_64_generic.s b/src/square_long_runtime_x86_64_generic.s index 7edfe52a..bb794542 100644 --- a/src/square_long_runtime_x86_64_generic.s +++ b/src/square_long_runtime_x86_64_generic.s @@ -4,15 +4,25 @@ .intel_syntax noprefix # Empty, but present, GNU-stack section +.ifndef BEMAN_BIG_INT_MACHO .section .note.GNU-stack,"",%progbits +.endif # Enter the text section for code/symbols +.ifdef BEMAN_BIG_INT_MACHO +.text +.else .section .text +.endif # Schoolbook squaring, baseline x86-64 only (no SSE/AVX, no BMI2/ADX). +.ifdef BEMAN_BIG_INT_MACHO +.globl _beman_big_int_square_long_runtime_generic +.else .globl beman_big_int_square_long_runtime_generic .type beman_big_int_square_long_runtime_generic, @function +.endif # rdi -> p_result # rsi -> p_a @@ -93,6 +103,9 @@ .endm +.ifdef BEMAN_BIG_INT_MACHO +_beman_big_int_square_long_runtime_generic: +.endif beman_big_int_square_long_runtime_generic: .cfi_startproc @@ -101,7 +114,7 @@ beman_big_int_square_long_runtime_generic: .cfi_rel_offset rbx, 0 cmp rdx, 1 - jbe .Lgeneric_x64_sqr_tiny # with at most one limb there is no triangle + jbe Lgeneric_x64_sqr_tiny # with at most one limb there is no triangle mov r9, rdx # free up rdx for the mul instruction @@ -117,23 +130,23 @@ beman_big_int_square_long_runtime_generic: GENERIC_X64_SQR_ROW_SETUP cmp rbx, rcx - je .Lgeneric_x64_sqr_mul_row_4x + je Lgeneric_x64_sqr_mul_row_4x -.Lgeneric_x64_sqr_mul_row_rmdr: +Lgeneric_x64_sqr_mul_row_rmdr: GENERIC_X64_MUL_LIMB 0 add rbx, 1 # j++ cmp rbx, rcx - jne .Lgeneric_x64_sqr_mul_row_rmdr # if (j != -(row_len & ~3)) { goto rmdr_loop_start; } + jne Lgeneric_x64_sqr_mul_row_rmdr # if (j != -(row_len & ~3)) { goto rmdr_loop_start; } -.Lgeneric_x64_sqr_mul_row_4x: +Lgeneric_x64_sqr_mul_row_4x: test rbx, rbx - jz .Lgeneric_x64_sqr_mul_row_end + jz Lgeneric_x64_sqr_mul_row_end .p2align 4 -.Lgeneric_x64_sqr_mul_row_4x_unroll: +Lgeneric_x64_sqr_mul_row_4x_unroll: GENERIC_X64_MUL_LIMB 0 GENERIC_X64_MUL_LIMB 8 @@ -141,39 +154,39 @@ beman_big_int_square_long_runtime_generic: GENERIC_X64_MUL_LIMB 24 add rbx, 4 # j += 4 - jnz .Lgeneric_x64_sqr_mul_row_4x_unroll # if (j != 0) { goto unroll_loop_start; } + jnz Lgeneric_x64_sqr_mul_row_4x_unroll # if (j != 0) { goto unroll_loop_start; } -.Lgeneric_x64_sqr_mul_row_end: +Lgeneric_x64_sqr_mul_row_end: mov QWORD PTR [rdi], r11 # result[len_a] = temp add rdi, 8 # increment the result ptr for next iter sub r8, 1 # row_len-- - jz .Lgeneric_x64_sqr_diag # len_a == 2: the triangle is a single limb + jz Lgeneric_x64_sqr_diag # len_a == 2: the triangle is a single limb .p2align 4 -.Lgeneric_x64_sqr_outer_loop_start: +Lgeneric_x64_sqr_outer_loop_start: GENERIC_X64_SQR_ROW_SETUP cmp rbx, rcx - je .Lgeneric_x64_sqr_inner_loop_4x + je Lgeneric_x64_sqr_inner_loop_4x -.Lgeneric_x64_sqr_inner_loop_rmdr: +Lgeneric_x64_sqr_inner_loop_rmdr: GENERIC_X64_ADDMUL_LIMB 0 add rbx, 1 # j++ cmp rbx, rcx - jne .Lgeneric_x64_sqr_inner_loop_rmdr # if (j != -(row_len & ~3)) { goto rmdr_loop_start; } + jne Lgeneric_x64_sqr_inner_loop_rmdr # if (j != -(row_len & ~3)) { goto rmdr_loop_start; } -.Lgeneric_x64_sqr_inner_loop_4x: +Lgeneric_x64_sqr_inner_loop_4x: test rbx, rbx - jz .Lgeneric_x64_sqr_outer_loop_end + jz Lgeneric_x64_sqr_outer_loop_end .p2align 4 -.Lgeneric_x64_sqr_inner_loop_4x_unroll: +Lgeneric_x64_sqr_inner_loop_4x_unroll: GENERIC_X64_ADDMUL_LIMB 0 GENERIC_X64_ADDMUL_LIMB 8 @@ -181,17 +194,17 @@ beman_big_int_square_long_runtime_generic: GENERIC_X64_ADDMUL_LIMB 24 add rbx, 4 # j += 4 - jnz .Lgeneric_x64_sqr_inner_loop_4x_unroll # if (j != 0) { goto unroll_loop_start; } + jnz Lgeneric_x64_sqr_inner_loop_4x_unroll # if (j != 0) { goto unroll_loop_start; } -.Lgeneric_x64_sqr_outer_loop_end: +Lgeneric_x64_sqr_outer_loop_end: mov QWORD PTR [rdi], r11 # result[len_a + i] = temp add rdi, 8 # increment the result ptr for next iter sub r8, 1 # row_len-- - jnz .Lgeneric_x64_sqr_outer_loop_start # if (row_len != 0) { goto outer_loop_start; } + jnz Lgeneric_x64_sqr_outer_loop_start # if (row_len != 0) { goto outer_loop_start; } -.Lgeneric_x64_sqr_diag: +Lgeneric_x64_sqr_diag: # The triangle occupies result[1 .. 2 * len_a - 2]; zero its two missing # end limbs so the pass below can treat every limb pair alike. rdi now @@ -213,7 +226,7 @@ beman_big_int_square_long_runtime_generic: # only one add/adc/adc run is loop-carried; a[i] sits at [rsi + rbx * 4]. .p2align 4 -.Lgeneric_x64_sqr_diag_loop: +Lgeneric_x64_sqr_diag_loop: mov rax, QWORD PTR [rsi + rbx * 4] # rax = a[i] mul rax # rdx : rax = a[i]^2 @@ -239,25 +252,27 @@ beman_big_int_square_long_runtime_generic: mov r11, r10 # extra = next_extra add rbx, 2 # i++ - jnz .Lgeneric_x64_sqr_diag_loop # if (i != len_a) { goto diag_loop_start; } + jnz Lgeneric_x64_sqr_diag_loop # if (i != len_a) { goto diag_loop_start; } - jmp .Lgeneric_x64_sqr_end + jmp Lgeneric_x64_sqr_end -.Lgeneric_x64_sqr_tiny: +Lgeneric_x64_sqr_tiny: test rdx, rdx # an empty operand leaves nothing to do - jz .Lgeneric_x64_sqr_end + jz Lgeneric_x64_sqr_end mov rax, QWORD PTR [rsi] # rax = a[0] mul rax # rdx : rax = a[0]^2 mov QWORD PTR [rdi], rax # result[0] = low64 mov QWORD PTR [rdi + 8], rdx # result[1] = high64 -.Lgeneric_x64_sqr_end: +Lgeneric_x64_sqr_end: pop rbx .cfi_adjust_cfa_offset -8 ret .cfi_endproc +.ifndef BEMAN_BIG_INT_MACHO .size beman_big_int_square_long_runtime_generic, .-beman_big_int_square_long_runtime_generic +.endif From f6d27d60b3f550ee5b52fa6b6bea53ae50859ae3 Mon Sep 17 00:00:00 2001 From: Colin Ford Date: Tue, 20 Oct 2026 19:13:04 -0700 Subject: [PATCH 2/5] Add appleclang presets on macos-15-intel to CI --- .github/workflows/ci_tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index fdfd05fb..f0908408 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -30,6 +30,8 @@ jobs: {"preset": "llvm-release", "image": "ghcr.io/bemanproject/infra-containers-clang:latest"}, {"preset": "appleclang-debug", "runner": "macos-latest"}, {"preset": "appleclang-release", "runner": "macos-latest"}, + {"preset": "appleclang-debug", "runner": "macos-15-intel"}, + {"preset": "appleclang-release", "runner": "macos-15-intel"}, {"preset": "msvc-debug", "runner": "windows-latest"}, {"preset": "msvc-release", "runner": "windows-latest"}, {"preset": "llvm-debug-simd", "image": "ghcr.io/bemanproject/infra-containers-clang:latest"}, From abf8378157337f9f036c4ed7bb8379e1cab607f1 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 26 Oct 2026 14:06:37 -0400 Subject: [PATCH 3/5] Lint Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c9af70e0..fe10f534 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,7 +209,8 @@ if( if(APPLE) target_compile_options( beman.big_int - PRIVATE $<$:-Wa,--defsym,BEMAN_BIG_INT_MACHO=1> + PRIVATE + $<$:-Wa,--defsym,BEMAN_BIG_INT_MACHO=1> ) endif() elseif( From 0b320b18bcf9d1b71de880e8bbd542711d254814 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 26 Oct 2026 15:28:14 -0400 Subject: [PATCH 4/5] Skip ICE tests on x64 Apple Machines --- tests/beman/big_int/multi_limb_construction.test.cpp | 9 ++++++++- tests/beman/big_int/numeric.test.cpp | 11 +++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/beman/big_int/multi_limb_construction.test.cpp b/tests/beman/big_int/multi_limb_construction.test.cpp index 28c3c7d0..27d60bab 100644 --- a/tests/beman/big_int/multi_limb_construction.test.cpp +++ b/tests/beman/big_int/multi_limb_construction.test.cpp @@ -15,8 +15,15 @@ // `__int128` and `_BitInt` are guarded individually since each is only // conditionally available. + +#if defined(__APPLE__) && defined(__x86_64__) + +TEST(MultiLimbConstruction, SkippedUnderAppleX64) { + GTEST_SKIP() << "Skipped: Apple Clang on x64 crashes compiling these tests."; +} + // clang-19 totally crashes running these tests -#if defined(__clang__) && __clang_major__ == 19 +#elif defined(__clang__) && __clang_major__ == 19 TEST(MultiLimbConstruction, SkippedUnderClang19) { GTEST_SKIP() << "Skipped: clang-19 crashes compiling these tests."; diff --git a/tests/beman/big_int/numeric.test.cpp b/tests/beman/big_int/numeric.test.cpp index 38fcc531..57e851fd 100644 --- a/tests/beman/big_int/numeric.test.cpp +++ b/tests/beman/big_int/numeric.test.cpp @@ -17,6 +17,15 @@ #include "testing.hpp" +// ICE with Apple Clang on x64 +#if defined(__APPLE__) && defined(__x86_64__) + +TEST(Numeric, SkippedUnderAppleX64) { + GTEST_SKIP() << "Skipped: Apple Clang on x64 crashes compiling these tests."; +} + +#else + namespace { using BEMAN_BIG_INT_NAMESPACE::abs; @@ -953,3 +962,5 @@ TEST(SaturatingCast, BitPreciseIntegers) { #endif } // namespace + +#endif From 1b1b7f15b639d84ccc84e34b79dd286128f90762 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Mon, 26 Oct 2026 15:30:29 -0400 Subject: [PATCH 5/5] Lint --- .../big_int/multi_limb_construction.test.cpp | 1 - tests/beman/big_int/numeric.test.cpp | 24 +++++++++---------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/tests/beman/big_int/multi_limb_construction.test.cpp b/tests/beman/big_int/multi_limb_construction.test.cpp index 27d60bab..43f47fa9 100644 --- a/tests/beman/big_int/multi_limb_construction.test.cpp +++ b/tests/beman/big_int/multi_limb_construction.test.cpp @@ -15,7 +15,6 @@ // `__int128` and `_BitInt` are guarded individually since each is only // conditionally available. - #if defined(__APPLE__) && defined(__x86_64__) TEST(MultiLimbConstruction, SkippedUnderAppleX64) { diff --git a/tests/beman/big_int/numeric.test.cpp b/tests/beman/big_int/numeric.test.cpp index 57e851fd..6ebb1d3e 100644 --- a/tests/beman/big_int/numeric.test.cpp +++ b/tests/beman/big_int/numeric.test.cpp @@ -20,9 +20,7 @@ // ICE with Apple Clang on x64 #if defined(__APPLE__) && defined(__x86_64__) -TEST(Numeric, SkippedUnderAppleX64) { - GTEST_SKIP() << "Skipped: Apple Clang on x64 crashes compiling these tests."; -} +TEST(Numeric, SkippedUnderAppleX64) { GTEST_SKIP() << "Skipped: Apple Clang on x64 crashes compiling these tests."; } #else @@ -563,7 +561,7 @@ TEST(Gcd, CallableFullyQualified) { EXPECT_EQ(BEMAN_BIG_INT_NAMESPACE::gcd(big_int{270}, 192), 6); } -#ifdef BEMAN_BIG_INT_HAS_BITINT + #ifdef BEMAN_BIG_INT_HAS_BITINT TEST(Gcd, BitPreciseIntegers) { // Bit-precise operands go through the same path as the standard integer types. using u12 = bit_uint<12>; @@ -572,14 +570,14 @@ TEST(Gcd, BitPreciseIntegers) { EXPECT_EQ(gcd(static_cast(1071), big_int{462}), 21); EXPECT_EQ(gcd((big_int{1} << 300) * 15, static_cast(35)), 5); - #if BEMAN_BIG_INT_BITINT_MAXWIDTH >= 96 + #if BEMAN_BIG_INT_BITINT_MAXWIDTH >= 96 // An operand wider than a limb is spelled out into limbs before the reduction. using s96 = bit_int<96>; EXPECT_EQ(gcd((big_int{1} << 300) * 15, static_cast(-35)), 5); EXPECT_EQ(gcd(big_int{1} << 300, static_cast(1) << 80), big_int{1} << 80); - #endif + #endif } -#endif + #endif // ============================================================================ // lcm @@ -924,7 +922,7 @@ TEST(Lcm, CallableFullyQualified) { EXPECT_EQ(BEMAN_BIG_INT_NAMESPACE::lcm(big_int{270}, 192), 8640); } -#ifdef BEMAN_BIG_INT_HAS_BITINT + #ifdef BEMAN_BIG_INT_HAS_BITINT TEST(Lcm, BitPreciseIntegers) { // Bit-precise operands go through the same path as the standard integer types. using u12 = bit_uint<12>; @@ -933,16 +931,16 @@ TEST(Lcm, BitPreciseIntegers) { EXPECT_EQ(lcm(static_cast(1071), big_int{462}), 23562); EXPECT_EQ(lcm((big_int{1} << 300) * 15, static_cast(35)), (big_int{1} << 300) * 105); - #if BEMAN_BIG_INT_BITINT_MAXWIDTH >= 96 + #if BEMAN_BIG_INT_BITINT_MAXWIDTH >= 96 // An operand wider than a limb is spelled out into limbs first. using s96 = bit_int<96>; EXPECT_EQ(lcm((big_int{1} << 300) * 15, static_cast(-35)), (big_int{1} << 300) * 105); EXPECT_EQ(lcm(big_int{1} << 300, static_cast(1) << 80), big_int{1} << 300); - #endif + #endif } -#endif + #endif -#ifdef BEMAN_BIG_INT_HAS_BITINT + #ifdef BEMAN_BIG_INT_HAS_BITINT TEST(SaturatingCast, BitPreciseIntegers) { // Extended/bit-precise integers (no std::numeric_limits specialization) use // the width-derived bounds. Results are widened to standard types so the @@ -959,7 +957,7 @@ TEST(SaturatingCast, BitPreciseIntegers) { EXPECT_EQ(static_cast(saturating_cast(big_int{-2048})), -2048); // -2^11 EXPECT_EQ(static_cast(saturating_cast(big_int{-2049})), -2048); // clamps to min } -#endif + #endif } // namespace