mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Merge remote-tracking branch 'origin/master' into llvm14
This commit is contained in:
commit
c89dd15e1b
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
contact_links:
|
||||
- name: Language Proposal
|
||||
about: Propose to improve the Zig language
|
||||
url: https://github.com/ziglang/zig/wiki/Language-Proposals
|
||||
- name: Question
|
||||
about: Please use one of the community spaces for questions or general discussions.
|
||||
url: https://github.com/ziglang/zig/wiki/Community
|
||||
16
.github/ISSUE_TEMPLATE/proposal.yml
vendored
16
.github/ISSUE_TEMPLATE/proposal.yml
vendored
@ -1,16 +0,0 @@
|
||||
name: Language Proposal
|
||||
description: Propose to improve the Zig language
|
||||
labels: ["proposal"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for your interest in improving the Zig language. However, we are
|
||||
not accepting new proposals to change the language at this time.
|
||||
- type: checkboxes
|
||||
id: trash
|
||||
attributes:
|
||||
label: Please do not file a proposal to change the language
|
||||
options:
|
||||
- label: "I understand, thank you. I will not submit a new proposal at this time"
|
||||
required: true
|
||||
20
.github/ISSUE_TEMPLATE/question.yml
vendored
20
.github/ISSUE_TEMPLATE/question.yml
vendored
@ -1,20 +0,0 @@
|
||||
name: Question
|
||||
description: Ask a Zig-related question
|
||||
labels: ["question"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Welcome! There are a bunch of great places to ask Zig-related questions.
|
||||
Please take a look at
|
||||
[The Community Wiki Page](https://github.com/ziglang/zig/wiki/Community) and
|
||||
find a comfy place to ask questions. You will find plenty of helpful people in
|
||||
these spaces. However, this issue tracker is not for questions. It is for
|
||||
more actionable items such as bug reports and enhancements.
|
||||
- type: checkboxes
|
||||
id: trash
|
||||
attributes:
|
||||
label: Please do not open a question issue on the bug tracker
|
||||
options:
|
||||
- label: "I understand, thank you. I will take my question to one of the community spaces instead"
|
||||
required: true
|
||||
275
CMakeLists.txt
275
CMakeLists.txt
@ -12,7 +12,7 @@ if(NOT CMAKE_BUILD_TYPE)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_INSTALL_PREFIX)
|
||||
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}" CACHE STRING
|
||||
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/stage1" CACHE STRING
|
||||
"Directory to install zig to" FORCE)
|
||||
endif()
|
||||
|
||||
@ -63,7 +63,7 @@ if("${ZIG_VERSION}" STREQUAL "")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
message("Configuring zig version ${ZIG_VERSION}")
|
||||
message(STATUS "Configuring zig version ${ZIG_VERSION}")
|
||||
|
||||
set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)")
|
||||
set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries")
|
||||
@ -398,6 +398,9 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/debug.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/dwarf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/dwarf/AT.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/dwarf/ATE.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/dwarf/FORM.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/dwarf/LANG.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/dwarf/OP.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/dwarf/TAG.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/elf.zig"
|
||||
@ -441,9 +444,8 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/math.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/math/big.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/math/big/int.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/math/floor.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/math/float.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/math/frexp.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/math/inf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/math/isinf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/math/isnan.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/math/ln.zig"
|
||||
@ -460,12 +462,14 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/meta/trait.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/multi_array_list.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os/darwin.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os/linux.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os/linux/errno/generic.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os/linux/x86_64.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os/linux.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os/linux/io_uring.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os/linux/x86_64.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os/posix_spawn.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os/windows.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os/windows/ntstatus.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/os/windows/win32error.zig"
|
||||
@ -474,74 +478,180 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/process.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/rand.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/sort.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/absv.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/addXf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/atomics.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/bswap.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/clear_cache.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/cmp.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/compareXf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/count0bits.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/divdf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/divsf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/divtf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/divti3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/extendXfYf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixdfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixdfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixdfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixint.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixsfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixsfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixsfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixtfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixtfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixtfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixuint.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixunsdfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixunsdfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixunsdfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixunssfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixunssfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixunssfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixunstfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixunstfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/fixunstfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatXisf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatdidf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatditf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatsiXf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floattidf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floattitf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatundidf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatundisf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatunditf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatunsidf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatunsisf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatunsitf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatuntidf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatuntisf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/floatuntitf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/int.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/modti3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/mulXf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/muldi3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/mulo.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/multi3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/negXf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/negXi2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/negv.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/os_version_check.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/parity.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/popcount.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/shift.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/stack_probe.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/truncXfYf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/udivmod.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/udivmodti4.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/udivti3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt/umodti3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/absv.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/absvdi2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/absvsi2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/absvti2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/adddf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/addf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/addo.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/addsf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/addtf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/addxf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/arm.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/atomics.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/aulldiv.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/aullrem.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/bswap.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/ceil.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/clear_cache.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmp.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmpdf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmpsf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmptf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmpxf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/common.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/comparef.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/cos.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/count0bits.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/divdf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/divsf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/divtf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/divti3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/divxf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/emutls.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/exp.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/exp2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/extenddftf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/extenddfxf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendhfsf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendhftf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendhfxf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendsfdf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendsftf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendsfxf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendxftf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fabs.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixdfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixdfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixdfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixhfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixhfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixhfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixsfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixsfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixsfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixtfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixtfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixtfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsdfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsdfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsdfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunshfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunshfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunshfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunssfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunssfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunssfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunstfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunstfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunstfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsxfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsxfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsxfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixxfdi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixxfsi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixxfti.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/float_to_int.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdidf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdihf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdisf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatditf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdixf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsidf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsihf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsisf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsitf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsixf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattidf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattihf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattisf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattitf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattixf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundidf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundihf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundisf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunditf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundixf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsidf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsihf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsisf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsitf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsixf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntidf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntihf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntisf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntitf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntixf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/floor.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fma.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fmax.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fmin.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/fmod.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/gedf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/gesf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/getf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/gexf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/int.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/int_to_float.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/log.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/log10.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/log2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/modti3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/muldf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/muldi3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulo.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulsf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/multf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/multi3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulxf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/negXi2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/negv.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/os_version_check.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/parity.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/popcount.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/rem_pio2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/rem_pio2_large.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/rem_pio2f.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/round.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/shift.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/sin.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/sincos.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/sqrt.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/stack_probe.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/subo.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/subsf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/subdf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/subtf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/subxf3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/negsf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/negdf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/negtf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/negxf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/tan.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/trig.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunc.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncdfhf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncdfsf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncf.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncsfhf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunctfdf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunctfhf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunctfsf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunctfxf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncxfdf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncxfhf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncxfsf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivmod.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivmodti4.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivti3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/umodti3.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/unorddf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/unordsf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/compiler_rt/unordtf2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/start.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/std.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/target.zig"
|
||||
@ -561,16 +671,16 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/target/wasm.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/target/x86.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/Thread.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/Thread/AutoResetEvent.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/Thread/Futex.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/Thread/Mutex.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/Thread/ResetEvent.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/Thread/StaticResetEvent.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/time.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/treap.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/unicode.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/zig.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/zig/Ast.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/zig/CrossTarget.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/zig/c_builtins.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/zig/parse.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/zig/render.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/zig/string_literal.zig"
|
||||
@ -597,14 +707,22 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/aarch64/Emit.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/aarch64/Mir.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/aarch64/bits.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/aarch64/abi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/arm/CodeGen.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/arm/Emit.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/arm/Mir.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/arm/bits.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/arm/abi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/riscv64/CodeGen.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/riscv64/Emit.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/riscv64/Mir.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/riscv64/bits.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/riscv64/abi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/sparc64/CodeGen.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/sparc64/Emit.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/sparc64/Mir.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/sparc64/bits.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/sparc64/abi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/wasm/CodeGen.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/wasm/Emit.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/wasm/Mir.zig"
|
||||
@ -612,6 +730,7 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/x86_64/Emit.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/x86_64/Mir.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/x86_64/bits.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/arch/x86_64/abi.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/clang.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/clang_options.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/clang_options_data.zig"
|
||||
@ -655,6 +774,7 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/src/print_env.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/print_targets.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/print_zir.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/register_manager.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/stage1.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/target.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/tracy.zig"
|
||||
@ -791,6 +911,9 @@ add_library(opt_c_util STATIC ${OPTIMIZED_C_SOURCES})
|
||||
set_target_properties(opt_c_util PROPERTIES
|
||||
COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}"
|
||||
)
|
||||
target_include_directories(opt_c_util PRIVATE
|
||||
"${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e-prebuilt"
|
||||
)
|
||||
|
||||
add_library(zigstage1 STATIC ${STAGE1_SOURCES})
|
||||
set_target_properties(zigstage1 PROPERTIES
|
||||
@ -834,7 +957,7 @@ else()
|
||||
set(ZIG1_RELEASE_ARG -OReleaseFast --strip)
|
||||
endif()
|
||||
if(ZIG_SINGLE_THREADED)
|
||||
set(ZIG1_SINGLE_THREADED_ARG "--single-threaded")
|
||||
set(ZIG1_SINGLE_THREADED_ARG "-fsingle-threaded")
|
||||
else()
|
||||
set(ZIG1_SINGLE_THREADED_ARG "")
|
||||
endif()
|
||||
@ -852,7 +975,7 @@ set(BUILD_ZIG1_ARGS
|
||||
-lc
|
||||
--pkg-begin build_options "${ZIG_CONFIG_ZIG_OUT}"
|
||||
--pkg-end
|
||||
--pkg-begin compiler_rt "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt.zig"
|
||||
--pkg-begin compiler_rt "${CMAKE_SOURCE_DIR}/lib/compiler_rt.zig"
|
||||
--pkg-end
|
||||
)
|
||||
|
||||
|
||||
@ -9,8 +9,8 @@ A general-purpose programming language and toolchain for maintaining
|
||||
* [Download & Documentation](https://ziglang.org/download)
|
||||
* [Chapter 0 - Getting Started | ZigLearn.org](https://ziglearn.org/)
|
||||
* [Community](https://github.com/ziglang/zig/wiki/Community)
|
||||
* [Contributing](https://github.com/ziglang/zig/blob/master/CONTRIBUTING.md)
|
||||
* [Code of Conduct](https://github.com/ziglang/zig/blob/master/CODE_OF_CONDUCT.md)
|
||||
* [Contributing](https://github.com/ziglang/zig/blob/master/.github/CONTRIBUTING.md)
|
||||
* [Code of Conduct](https://github.com/ziglang/zig/blob/master/.github/CODE_OF_CONDUCT.md)
|
||||
* [Frequently Asked Questions](https://github.com/ziglang/zig/wiki/FAQ)
|
||||
* [Community Projects](https://github.com/ziglang/zig/wiki/Community-Projects)
|
||||
|
||||
|
||||
312
build.zig
312
build.zig
@ -19,7 +19,7 @@ pub fn build(b: *Builder) !void {
|
||||
const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode");
|
||||
const use_zig_libcxx = b.option(bool, "use-zig-libcxx", "If libc++ is needed, use zig's bundled version, don't try to integrate with the system") orelse false;
|
||||
|
||||
var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
|
||||
const docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
|
||||
docgen_exe.single_threaded = single_threaded;
|
||||
|
||||
const rel_zig_exe = try fs.path.relative(b.allocator, b.build_root, b.zig_exe);
|
||||
@ -27,7 +27,7 @@ pub fn build(b: *Builder) !void {
|
||||
b.allocator,
|
||||
&[_][]const u8{ b.cache_root, "langref.html" },
|
||||
) catch unreachable;
|
||||
var docgen_cmd = docgen_exe.run();
|
||||
const docgen_cmd = docgen_exe.run();
|
||||
docgen_cmd.addArgs(&[_][]const u8{
|
||||
rel_zig_exe,
|
||||
"doc" ++ fs.path.sep_str ++ "langref.html.in",
|
||||
@ -40,10 +40,10 @@ pub fn build(b: *Builder) !void {
|
||||
|
||||
const toolchain_step = b.step("test-toolchain", "Run the tests for the toolchain");
|
||||
|
||||
var test_stage2 = b.addTest("src/test.zig");
|
||||
test_stage2.setBuildMode(mode);
|
||||
test_stage2.addPackagePath("test_cases", "test/cases.zig");
|
||||
test_stage2.single_threaded = single_threaded;
|
||||
var test_cases = b.addTest("src/test.zig");
|
||||
test_cases.setBuildMode(mode);
|
||||
test_cases.addPackagePath("test_cases", "test/cases.zig");
|
||||
test_cases.single_threaded = single_threaded;
|
||||
|
||||
const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"});
|
||||
|
||||
@ -54,12 +54,14 @@ pub fn build(b: *Builder) !void {
|
||||
const skip_release_safe = b.option(bool, "skip-release-safe", "Main test suite skips release-safe builds") orelse skip_release;
|
||||
const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false;
|
||||
const skip_libc = b.option(bool, "skip-libc", "Main test suite skips tests that link libc") orelse false;
|
||||
const skip_compile_errors = b.option(bool, "skip-compile-errors", "Main test suite skips compile error tests") orelse false;
|
||||
const skip_single_threaded = b.option(bool, "skip-single-threaded", "Main test suite skips tests that are single-threaded") orelse false;
|
||||
const skip_stage1 = b.option(bool, "skip-stage1", "Main test suite skips stage1 compile error tests") orelse false;
|
||||
const skip_run_translated_c = b.option(bool, "skip-run-translated-c", "Main test suite skips run-translated-c tests") orelse false;
|
||||
const skip_stage2_tests = b.option(bool, "skip-stage2-tests", "Main test suite skips self-hosted compiler tests") orelse false;
|
||||
const skip_install_lib_files = b.option(bool, "skip-install-lib-files", "Do not copy lib/ files to installation prefix") orelse false;
|
||||
|
||||
const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false;
|
||||
|
||||
const is_stage1 = b.option(bool, "stage1", "Build the stage1 compiler, put stage2 behind a feature flag") orelse false;
|
||||
const omit_stage2 = b.option(bool, "omit-stage2", "Do not include stage2 behind a feature flag inside stage1") orelse false;
|
||||
const static_llvm = b.option(bool, "static-llvm", "Disable integration with system-installed LLVM, Clang, LLD, and libc++") orelse false;
|
||||
@ -128,6 +130,8 @@ pub fn build(b: *Builder) !void {
|
||||
const force_gpa = b.option(bool, "force-gpa", "Force the compiler to use GeneralPurposeAllocator") orelse false;
|
||||
const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm;
|
||||
const strip = b.option(bool, "strip", "Omit debug information") orelse false;
|
||||
const use_zig0 = b.option(bool, "zig0", "Bootstrap using zig0") orelse false;
|
||||
const value_tracing = b.option(bool, "value-tracing", "Enable extra state tracking to help troubleshoot bugs in the compiler (using the std.debug.Trace API)") orelse false;
|
||||
|
||||
const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: {
|
||||
if (strip) break :blk @as(u32, 0);
|
||||
@ -135,23 +139,29 @@ pub fn build(b: *Builder) !void {
|
||||
break :blk 4;
|
||||
};
|
||||
|
||||
const main_file = if (is_stage1) "src/stage1.zig" else "src/main.zig";
|
||||
const main_file: ?[]const u8 = mf: {
|
||||
if (!is_stage1) break :mf "src/main.zig";
|
||||
if (use_zig0) break :mf null;
|
||||
break :mf "src/stage1.zig";
|
||||
};
|
||||
|
||||
var exe = b.addExecutable("zig", main_file);
|
||||
const exe = b.addExecutable("zig", main_file);
|
||||
exe.strip = strip;
|
||||
exe.build_id = b.option(bool, "build-id", "Include a build id note") orelse false;
|
||||
exe.install();
|
||||
exe.setBuildMode(mode);
|
||||
exe.setTarget(target);
|
||||
if (!skip_stage2_tests) {
|
||||
toolchain_step.dependOn(&exe.step);
|
||||
}
|
||||
|
||||
b.default_step.dependOn(&exe.step);
|
||||
exe.single_threaded = single_threaded;
|
||||
|
||||
if (target.isWindows() and target.getAbi() == .gnu) {
|
||||
// LTO is currently broken on mingw, this can be removed when it's fixed.
|
||||
exe.want_lto = false;
|
||||
test_stage2.want_lto = false;
|
||||
test_cases.want_lto = false;
|
||||
}
|
||||
|
||||
const exe_options = b.addOptions();
|
||||
@ -166,59 +176,9 @@ pub fn build(b: *Builder) !void {
|
||||
exe_options.addOption(bool, "llvm_has_arc", llvm_has_arc);
|
||||
exe_options.addOption(bool, "force_gpa", force_gpa);
|
||||
|
||||
if (enable_llvm) {
|
||||
const cmake_cfg = if (static_llvm) null else findAndParseConfigH(b, config_h_path_option);
|
||||
|
||||
if (is_stage1) {
|
||||
exe.addIncludePath("src");
|
||||
exe.addIncludePath("deps/SoftFloat-3e/source/include");
|
||||
|
||||
test_stage2.addIncludePath("src");
|
||||
test_stage2.addIncludePath("deps/SoftFloat-3e/source/include");
|
||||
// This is intentionally a dummy path. stage1.zig tries to @import("compiler_rt") in case
|
||||
// of being built by cmake. But when built by zig it's gonna get a compiler_rt so that
|
||||
// is pointless.
|
||||
exe.addPackagePath("compiler_rt", "src/empty.zig");
|
||||
exe.defineCMacro("ZIG_LINK_MODE", "Static");
|
||||
test_stage2.defineCMacro("ZIG_LINK_MODE", "Static");
|
||||
|
||||
const softfloat = b.addStaticLibrary("softfloat", null);
|
||||
softfloat.setBuildMode(.ReleaseFast);
|
||||
softfloat.setTarget(target);
|
||||
softfloat.addIncludePath("deps/SoftFloat-3e-prebuilt");
|
||||
softfloat.addIncludePath("deps/SoftFloat-3e/source/8086");
|
||||
softfloat.addIncludePath("deps/SoftFloat-3e/source/include");
|
||||
softfloat.addCSourceFiles(&softfloat_sources, &[_][]const u8{ "-std=c99", "-O3" });
|
||||
softfloat.single_threaded = single_threaded;
|
||||
|
||||
exe.linkLibrary(softfloat);
|
||||
test_stage2.linkLibrary(softfloat);
|
||||
|
||||
exe.addCSourceFiles(&stage1_sources, &exe_cflags);
|
||||
exe.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" });
|
||||
|
||||
test_stage2.addCSourceFiles(&stage1_sources, &exe_cflags);
|
||||
test_stage2.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" });
|
||||
}
|
||||
if (cmake_cfg) |cfg| {
|
||||
// Inside this code path, we have to coordinate with system packaged LLVM, Clang, and LLD.
|
||||
// That means we also have to rely on stage1 compiled c++ files. We parse config.h to find
|
||||
// the information passed on to us from cmake.
|
||||
if (cfg.cmake_prefix_path.len > 0) {
|
||||
b.addSearchPrefix(cfg.cmake_prefix_path);
|
||||
}
|
||||
|
||||
try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx);
|
||||
try addCmakeCfgOptionsToExe(b, cfg, test_stage2, use_zig_libcxx);
|
||||
} else {
|
||||
// Here we are -Denable-llvm but no cmake integration.
|
||||
try addStaticLlvmOptionsToExe(exe);
|
||||
try addStaticLlvmOptionsToExe(test_stage2);
|
||||
}
|
||||
}
|
||||
if (link_libc) {
|
||||
exe.linkLibC();
|
||||
test_stage2.linkLibC();
|
||||
test_cases.linkLibC();
|
||||
}
|
||||
|
||||
const is_debug = mode == .Debug;
|
||||
@ -227,6 +187,10 @@ pub fn build(b: *Builder) !void {
|
||||
|
||||
const opt_version_string = b.option([]const u8, "version-string", "Override Zig version string. Default is to find out with git.");
|
||||
const version = if (opt_version_string) |version| version else v: {
|
||||
if (!std.process.can_spawn) {
|
||||
std.debug.print("error: version info cannot be retrieved from git. Zig version must be provided using -Dversion-string\n", .{});
|
||||
std.process.exit(1);
|
||||
}
|
||||
const version_string = b.fmt("{d}.{d}.{d}", .{ zig_version.major, zig_version.minor, zig_version.patch });
|
||||
|
||||
var code: u8 = undefined;
|
||||
@ -276,6 +240,112 @@ pub fn build(b: *Builder) !void {
|
||||
};
|
||||
exe_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version));
|
||||
|
||||
if (enable_llvm) {
|
||||
const cmake_cfg = if (static_llvm) null else findAndParseConfigH(b, config_h_path_option);
|
||||
|
||||
if (is_stage1) {
|
||||
const softfloat = b.addStaticLibrary("softfloat", null);
|
||||
softfloat.setBuildMode(.ReleaseFast);
|
||||
softfloat.setTarget(target);
|
||||
softfloat.addIncludePath("deps/SoftFloat-3e-prebuilt");
|
||||
softfloat.addIncludePath("deps/SoftFloat-3e/source/8086");
|
||||
softfloat.addIncludePath("deps/SoftFloat-3e/source/include");
|
||||
softfloat.addCSourceFiles(&softfloat_sources, &[_][]const u8{ "-std=c99", "-O3" });
|
||||
softfloat.single_threaded = single_threaded;
|
||||
|
||||
const zig0 = b.addExecutable("zig0", null);
|
||||
zig0.addCSourceFiles(&.{"src/stage1/zig0.cpp"}, &exe_cflags);
|
||||
zig0.addIncludePath("zig-cache/tmp"); // for config.h
|
||||
zig0.defineCMacro("ZIG_VERSION_MAJOR", b.fmt("{d}", .{zig_version.major}));
|
||||
zig0.defineCMacro("ZIG_VERSION_MINOR", b.fmt("{d}", .{zig_version.minor}));
|
||||
zig0.defineCMacro("ZIG_VERSION_PATCH", b.fmt("{d}", .{zig_version.patch}));
|
||||
zig0.defineCMacro("ZIG_VERSION_STRING", b.fmt("\"{s}\"", .{version}));
|
||||
|
||||
for ([_]*std.build.LibExeObjStep{ zig0, exe, test_cases }) |artifact| {
|
||||
artifact.addIncludePath("src");
|
||||
artifact.addIncludePath("deps/SoftFloat-3e/source/include");
|
||||
artifact.addIncludePath("deps/SoftFloat-3e-prebuilt");
|
||||
|
||||
artifact.defineCMacro("ZIG_LINK_MODE", "Static");
|
||||
|
||||
artifact.addCSourceFiles(&stage1_sources, &exe_cflags);
|
||||
artifact.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" });
|
||||
|
||||
artifact.linkLibrary(softfloat);
|
||||
artifact.linkLibCpp();
|
||||
}
|
||||
|
||||
try addStaticLlvmOptionsToExe(zig0);
|
||||
|
||||
const zig1_obj_ext = target.getObjectFormat().fileExt(target.getCpuArch());
|
||||
const zig1_obj_path = b.pathJoin(&.{ "zig-cache", "tmp", b.fmt("zig1{s}", .{zig1_obj_ext}) });
|
||||
const zig1_compiler_rt_path = b.pathJoin(&.{ b.pathFromRoot("lib"), "std", "special", "compiler_rt.zig" });
|
||||
|
||||
const zig1_obj = zig0.run();
|
||||
zig1_obj.addArgs(&.{
|
||||
"src/stage1.zig",
|
||||
"-target",
|
||||
try target.zigTriple(b.allocator),
|
||||
"-mcpu=baseline",
|
||||
"--name",
|
||||
"zig1",
|
||||
"--zig-lib-dir",
|
||||
b.pathFromRoot("lib"),
|
||||
b.fmt("-femit-bin={s}", .{b.pathFromRoot(zig1_obj_path)}),
|
||||
"-fcompiler-rt",
|
||||
"-lc",
|
||||
});
|
||||
{
|
||||
zig1_obj.addArgs(&.{ "--pkg-begin", "build_options" });
|
||||
zig1_obj.addFileSourceArg(exe_options.getSource());
|
||||
zig1_obj.addArgs(&.{ "--pkg-end", "--pkg-begin", "compiler_rt", zig1_compiler_rt_path, "--pkg-end" });
|
||||
}
|
||||
switch (mode) {
|
||||
.Debug => {},
|
||||
.ReleaseFast => {
|
||||
zig1_obj.addArg("-OReleaseFast");
|
||||
zig1_obj.addArg("--strip");
|
||||
},
|
||||
.ReleaseSafe => {
|
||||
zig1_obj.addArg("-OReleaseSafe");
|
||||
zig1_obj.addArg("--strip");
|
||||
},
|
||||
.ReleaseSmall => {
|
||||
zig1_obj.addArg("-OReleaseSmall");
|
||||
zig1_obj.addArg("--strip");
|
||||
},
|
||||
}
|
||||
if (single_threaded orelse false) {
|
||||
zig1_obj.addArg("-fsingle-threaded");
|
||||
}
|
||||
|
||||
if (use_zig0) {
|
||||
exe.step.dependOn(&zig1_obj.step);
|
||||
exe.addObjectFile(zig1_obj_path);
|
||||
}
|
||||
|
||||
// This is intentionally a dummy path. stage1.zig tries to @import("compiler_rt") in case
|
||||
// of being built by cmake. But when built by zig it's gonna get a compiler_rt so that
|
||||
// is pointless.
|
||||
exe.addPackagePath("compiler_rt", "src/empty.zig");
|
||||
}
|
||||
if (cmake_cfg) |cfg| {
|
||||
// Inside this code path, we have to coordinate with system packaged LLVM, Clang, and LLD.
|
||||
// That means we also have to rely on stage1 compiled c++ files. We parse config.h to find
|
||||
// the information passed on to us from cmake.
|
||||
if (cfg.cmake_prefix_path.len > 0) {
|
||||
b.addSearchPrefix(cfg.cmake_prefix_path);
|
||||
}
|
||||
|
||||
try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx);
|
||||
try addCmakeCfgOptionsToExe(b, cfg, test_cases, use_zig_libcxx);
|
||||
} else {
|
||||
// Here we are -Denable-llvm but no cmake integration.
|
||||
try addStaticLlvmOptionsToExe(exe);
|
||||
try addStaticLlvmOptionsToExe(test_cases);
|
||||
}
|
||||
}
|
||||
|
||||
const semver = try std.SemanticVersion.parse(version);
|
||||
exe_options.addOption(std.SemanticVersion, "semver", semver);
|
||||
|
||||
@ -284,6 +354,7 @@ pub fn build(b: *Builder) !void {
|
||||
exe_options.addOption(bool, "enable_tracy", tracy != null);
|
||||
exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);
|
||||
exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);
|
||||
exe_options.addOption(bool, "value_tracing", value_tracing);
|
||||
exe_options.addOption(bool, "is_stage1", is_stage1);
|
||||
exe_options.addOption(bool, "omit_stage2", omit_stage2);
|
||||
if (tracy) |tracy_path| {
|
||||
@ -313,34 +384,37 @@ pub fn build(b: *Builder) !void {
|
||||
|
||||
const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");
|
||||
|
||||
const test_stage2_options = b.addOptions();
|
||||
test_stage2.addOptions("build_options", test_stage2_options);
|
||||
const test_cases_options = b.addOptions();
|
||||
test_cases.addOptions("build_options", test_cases_options);
|
||||
|
||||
test_stage2_options.addOption(bool, "enable_logging", enable_logging);
|
||||
test_stage2_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
|
||||
test_stage2_options.addOption(bool, "skip_non_native", skip_non_native);
|
||||
test_stage2_options.addOption(bool, "skip_compile_errors", skip_compile_errors);
|
||||
test_stage2_options.addOption(bool, "is_stage1", is_stage1);
|
||||
test_stage2_options.addOption(bool, "omit_stage2", omit_stage2);
|
||||
test_stage2_options.addOption(bool, "have_llvm", enable_llvm);
|
||||
test_stage2_options.addOption(bool, "llvm_has_m68k", llvm_has_m68k);
|
||||
test_stage2_options.addOption(bool, "llvm_has_csky", llvm_has_csky);
|
||||
test_stage2_options.addOption(bool, "llvm_has_ve", llvm_has_ve);
|
||||
test_stage2_options.addOption(bool, "llvm_has_arc", llvm_has_arc);
|
||||
test_stage2_options.addOption(bool, "enable_qemu", b.enable_qemu);
|
||||
test_stage2_options.addOption(bool, "enable_wine", b.enable_wine);
|
||||
test_stage2_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime);
|
||||
test_stage2_options.addOption(bool, "enable_rosetta", b.enable_rosetta);
|
||||
test_stage2_options.addOption(bool, "enable_darling", b.enable_darling);
|
||||
test_stage2_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2);
|
||||
test_stage2_options.addOption(?[]const u8, "glibc_runtimes_dir", b.glibc_runtimes_dir);
|
||||
test_stage2_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version));
|
||||
test_stage2_options.addOption(std.SemanticVersion, "semver", semver);
|
||||
test_cases_options.addOption(bool, "enable_logging", enable_logging);
|
||||
test_cases_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
|
||||
test_cases_options.addOption(bool, "skip_non_native", skip_non_native);
|
||||
test_cases_options.addOption(bool, "skip_stage1", skip_stage1);
|
||||
test_cases_options.addOption(bool, "is_stage1", is_stage1);
|
||||
test_cases_options.addOption(bool, "omit_stage2", omit_stage2);
|
||||
test_cases_options.addOption(bool, "have_llvm", enable_llvm);
|
||||
test_cases_options.addOption(bool, "llvm_has_m68k", llvm_has_m68k);
|
||||
test_cases_options.addOption(bool, "llvm_has_csky", llvm_has_csky);
|
||||
test_cases_options.addOption(bool, "llvm_has_ve", llvm_has_ve);
|
||||
test_cases_options.addOption(bool, "llvm_has_arc", llvm_has_arc);
|
||||
test_cases_options.addOption(bool, "force_gpa", force_gpa);
|
||||
test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu);
|
||||
test_cases_options.addOption(bool, "enable_wine", b.enable_wine);
|
||||
test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime);
|
||||
test_cases_options.addOption(bool, "enable_rosetta", b.enable_rosetta);
|
||||
test_cases_options.addOption(bool, "enable_darling", b.enable_darling);
|
||||
test_cases_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2);
|
||||
test_cases_options.addOption(bool, "value_tracing", value_tracing);
|
||||
test_cases_options.addOption(?[]const u8, "glibc_runtimes_dir", b.glibc_runtimes_dir);
|
||||
test_cases_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version));
|
||||
test_cases_options.addOption(std.SemanticVersion, "semver", semver);
|
||||
test_cases_options.addOption(?[]const u8, "test_filter", test_filter);
|
||||
|
||||
const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");
|
||||
test_stage2_step.dependOn(&test_stage2.step);
|
||||
const test_cases_step = b.step("test-cases", "Run the main compiler test cases");
|
||||
test_cases_step.dependOn(&test_cases.step);
|
||||
if (!skip_stage2_tests) {
|
||||
toolchain_step.dependOn(test_stage2_step);
|
||||
toolchain_step.dependOn(test_cases_step);
|
||||
}
|
||||
|
||||
var chosen_modes: [4]builtin.Mode = undefined;
|
||||
@ -375,41 +449,50 @@ pub fn build(b: *Builder) !void {
|
||||
"behavior",
|
||||
"Run the behavior tests",
|
||||
modes,
|
||||
false, // skip_single_threaded
|
||||
skip_single_threaded,
|
||||
skip_non_native,
|
||||
skip_libc,
|
||||
skip_stage1,
|
||||
omit_stage2,
|
||||
is_stage1,
|
||||
));
|
||||
|
||||
toolchain_step.dependOn(tests.addPkgTests(
|
||||
b,
|
||||
test_filter,
|
||||
"lib/std/special/compiler_rt.zig",
|
||||
"lib/compiler_rt.zig",
|
||||
"compiler-rt",
|
||||
"Run the compiler_rt tests",
|
||||
modes,
|
||||
true, // skip_single_threaded
|
||||
skip_non_native,
|
||||
true, // skip_libc
|
||||
skip_stage1,
|
||||
omit_stage2 or true, // TODO get these all passing
|
||||
is_stage1,
|
||||
));
|
||||
|
||||
toolchain_step.dependOn(tests.addPkgTests(
|
||||
b,
|
||||
test_filter,
|
||||
"lib/std/special/c.zig",
|
||||
"minilibc",
|
||||
"Run the mini libc tests",
|
||||
"lib/c.zig",
|
||||
"universal-libc",
|
||||
"Run the universal libc tests",
|
||||
modes,
|
||||
true, // skip_single_threaded
|
||||
skip_non_native,
|
||||
true, // skip_libc
|
||||
skip_stage1,
|
||||
omit_stage2 or true, // TODO get these all passing
|
||||
is_stage1,
|
||||
));
|
||||
|
||||
toolchain_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
|
||||
toolchain_step.dependOn(tests.addStandaloneTests(b, test_filter, modes, skip_non_native, enable_macos_sdk, target));
|
||||
toolchain_step.dependOn(tests.addLinkTests(b, test_filter, modes, enable_macos_sdk));
|
||||
toolchain_step.dependOn(tests.addStackTraceTests(b, test_filter, modes));
|
||||
toolchain_step.dependOn(tests.addCliTests(b, test_filter, modes));
|
||||
toolchain_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
|
||||
toolchain_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
|
||||
toolchain_step.dependOn(tests.addTranslateCTests(b, test_filter));
|
||||
if (!skip_run_translated_c) {
|
||||
toolchain_step.dependOn(tests.addRunTranslatedCTests(b, test_filter, target));
|
||||
@ -424,9 +507,12 @@ pub fn build(b: *Builder) !void {
|
||||
"std",
|
||||
"Run the standard library tests",
|
||||
modes,
|
||||
false,
|
||||
skip_single_threaded,
|
||||
skip_non_native,
|
||||
skip_libc,
|
||||
skip_stage1,
|
||||
omit_stage2 or true, // TODO get these all passing
|
||||
is_stage1,
|
||||
);
|
||||
|
||||
const test_step = b.step("test", "Run all the tests");
|
||||
@ -499,9 +585,7 @@ fn addCmakeCfgOptionsToExe(
|
||||
}
|
||||
}
|
||||
|
||||
fn addStaticLlvmOptionsToExe(
|
||||
exe: *std.build.LibExeObjStep,
|
||||
) !void {
|
||||
fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep) !void {
|
||||
// Adds the Zig C++ sources which both stage1 and stage2 need.
|
||||
//
|
||||
// We need this because otherwise zig_clang_cc1_main.cpp ends up pulling
|
||||
@ -542,11 +626,14 @@ fn addCxxKnownPath(
|
||||
errtxt: ?[]const u8,
|
||||
need_cpp_includes: bool,
|
||||
) !void {
|
||||
if (!std.process.can_spawn)
|
||||
return error.RequiredLibraryNotFound;
|
||||
const path_padded = try b.exec(&[_][]const u8{
|
||||
ctx.cxx_compiler,
|
||||
b.fmt("-print-file-name={s}", .{objname}),
|
||||
});
|
||||
const path_unpadded = mem.tokenize(u8, path_padded, "\r\n").next().?;
|
||||
var tokenizer = mem.tokenize(u8, path_padded, "\r\n");
|
||||
const path_unpadded = tokenizer.next().?;
|
||||
if (mem.eql(u8, path_unpadded, objname)) {
|
||||
if (errtxt) |msg| {
|
||||
std.debug.print("{s}", .{msg});
|
||||
@ -688,15 +775,19 @@ fn toNativePathSep(b: *Builder, s: []const u8) []u8 {
|
||||
|
||||
const softfloat_sources = [_][]const u8{
|
||||
"deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/extF80M_isSignalingNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_extF80MToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_propagateNaNExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c",
|
||||
"deps/SoftFloat-3e/source/f128M_add.c",
|
||||
@ -716,6 +807,7 @@ const softfloat_sources = [_][]const u8{
|
||||
"deps/SoftFloat-3e/source/f128M_to_f16.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_f32.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_f64.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_i32.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_i32_r_minMag.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_i64.c",
|
||||
@ -724,6 +816,20 @@ const softfloat_sources = [_][]const u8{
|
||||
"deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_ui64.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_add.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_div.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_eq.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_le.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_lt.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_mul.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_rem.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_roundToInt.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_sqrt.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_sub.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f16.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f32.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f64.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f16_add.c",
|
||||
"deps/SoftFloat-3e/source/f16_div.c",
|
||||
"deps/SoftFloat-3e/source/f16_eq.c",
|
||||
@ -735,9 +841,12 @@ const softfloat_sources = [_][]const u8{
|
||||
"deps/SoftFloat-3e/source/f16_roundToInt.c",
|
||||
"deps/SoftFloat-3e/source/f16_sqrt.c",
|
||||
"deps/SoftFloat-3e/source/f16_sub.c",
|
||||
"deps/SoftFloat-3e/source/f16_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f16_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f16_to_f64.c",
|
||||
"deps/SoftFloat-3e/source/f32_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f32_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f64_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f64_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f64_to_f16.c",
|
||||
"deps/SoftFloat-3e/source/i32_to_f128M.c",
|
||||
@ -745,6 +854,7 @@ const softfloat_sources = [_][]const u8{
|
||||
"deps/SoftFloat-3e/source/s_addCarryM.c",
|
||||
"deps/SoftFloat-3e/source/s_addComplCarryM.c",
|
||||
"deps/SoftFloat-3e/source/s_addF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_addExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_addM.c",
|
||||
"deps/SoftFloat-3e/source/s_addMagsF16.c",
|
||||
"deps/SoftFloat-3e/source/s_addMagsF32.c",
|
||||
@ -755,12 +865,14 @@ const softfloat_sources = [_][]const u8{
|
||||
"deps/SoftFloat-3e/source/s_approxRecip_1Ks.c",
|
||||
"deps/SoftFloat-3e/source/s_compare128M.c",
|
||||
"deps/SoftFloat-3e/source/s_compare96M.c",
|
||||
"deps/SoftFloat-3e/source/s_compareNonnormExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros16.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros32.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros64.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros8.c",
|
||||
"deps/SoftFloat-3e/source/s_eq128.c",
|
||||
"deps/SoftFloat-3e/source/s_invalidF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_invalidExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_isNaNF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_le128.c",
|
||||
"deps/SoftFloat-3e/source/s_lt128.c",
|
||||
@ -771,7 +883,9 @@ const softfloat_sources = [_][]const u8{
|
||||
"deps/SoftFloat-3e/source/s_mulAddF32.c",
|
||||
"deps/SoftFloat-3e/source/s_mulAddF64.c",
|
||||
"deps/SoftFloat-3e/source/s_negXM.c",
|
||||
"deps/SoftFloat-3e/source/s_normExtF80SigM.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackMToF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackMToExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackToF16.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackToF32.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackToF64.c",
|
||||
@ -782,6 +896,7 @@ const softfloat_sources = [_][]const u8{
|
||||
"deps/SoftFloat-3e/source/s_remStepMBy32.c",
|
||||
"deps/SoftFloat-3e/source/s_roundMToI64.c",
|
||||
"deps/SoftFloat-3e/source/s_roundMToUI64.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackMToExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackMToF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackToF16.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackToF32.c",
|
||||
@ -810,9 +925,12 @@ const softfloat_sources = [_][]const u8{
|
||||
"deps/SoftFloat-3e/source/s_subMagsF32.c",
|
||||
"deps/SoftFloat-3e/source/s_subMagsF64.c",
|
||||
"deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_tryPropagateNaNExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/softfloat_state.c",
|
||||
"deps/SoftFloat-3e/source/ui32_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/ui64_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/ui32_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/ui64_to_extF80M.c",
|
||||
};
|
||||
|
||||
const stage1_sources = [_][]const u8{
|
||||
|
||||
980
ci/azure/build.zig
Normal file
980
ci/azure/build.zig
Normal file
@ -0,0 +1,980 @@
|
||||
const std = @import("std");
|
||||
const builtin = std.builtin;
|
||||
const Builder = std.build.Builder;
|
||||
const BufMap = std.BufMap;
|
||||
const mem = std.mem;
|
||||
const ArrayList = std.ArrayList;
|
||||
const io = std.io;
|
||||
const fs = std.fs;
|
||||
const InstallDirectoryOptions = std.build.InstallDirectoryOptions;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const zig_version = std.builtin.Version{ .major = 0, .minor = 10, .patch = 0 };
|
||||
|
||||
pub fn build(b: *Builder) !void {
|
||||
b.setPreferredReleaseMode(.ReleaseFast);
|
||||
const mode = b.standardReleaseOptions();
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode");
|
||||
const use_zig_libcxx = b.option(bool, "use-zig-libcxx", "If libc++ is needed, use zig's bundled version, don't try to integrate with the system") orelse false;
|
||||
|
||||
const docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
|
||||
docgen_exe.single_threaded = single_threaded;
|
||||
|
||||
const rel_zig_exe = try fs.path.relative(b.allocator, b.build_root, b.zig_exe);
|
||||
const langref_out_path = fs.path.join(
|
||||
b.allocator,
|
||||
&[_][]const u8{ b.cache_root, "langref.html" },
|
||||
) catch unreachable;
|
||||
const docgen_cmd = docgen_exe.run();
|
||||
docgen_cmd.addArgs(&[_][]const u8{
|
||||
rel_zig_exe,
|
||||
"doc" ++ fs.path.sep_str ++ "langref.html.in",
|
||||
langref_out_path,
|
||||
});
|
||||
docgen_cmd.step.dependOn(&docgen_exe.step);
|
||||
|
||||
const docs_step = b.step("docs", "Build documentation");
|
||||
docs_step.dependOn(&docgen_cmd.step);
|
||||
|
||||
const is_stage1 = b.option(bool, "stage1", "Build the stage1 compiler, put stage2 behind a feature flag") orelse false;
|
||||
const omit_stage2 = b.option(bool, "omit-stage2", "Do not include stage2 behind a feature flag inside stage1") orelse false;
|
||||
const static_llvm = b.option(bool, "static-llvm", "Disable integration with system-installed LLVM, Clang, LLD, and libc++") orelse false;
|
||||
const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse (is_stage1 or static_llvm);
|
||||
const llvm_has_m68k = b.option(
|
||||
bool,
|
||||
"llvm-has-m68k",
|
||||
"Whether LLVM has the experimental target m68k enabled",
|
||||
) orelse false;
|
||||
const llvm_has_csky = b.option(
|
||||
bool,
|
||||
"llvm-has-csky",
|
||||
"Whether LLVM has the experimental target csky enabled",
|
||||
) orelse false;
|
||||
const llvm_has_ve = b.option(
|
||||
bool,
|
||||
"llvm-has-ve",
|
||||
"Whether LLVM has the experimental target ve enabled",
|
||||
) orelse false;
|
||||
const llvm_has_arc = b.option(
|
||||
bool,
|
||||
"llvm-has-arc",
|
||||
"Whether LLVM has the experimental target arc enabled",
|
||||
) orelse false;
|
||||
const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h");
|
||||
|
||||
b.installDirectory(InstallDirectoryOptions{
|
||||
.source_dir = "lib",
|
||||
.install_dir = .lib,
|
||||
.install_subdir = "zig",
|
||||
.exclude_extensions = &[_][]const u8{
|
||||
// exclude files from lib/std/compress/
|
||||
".gz",
|
||||
".z.0",
|
||||
".z.9",
|
||||
"rfc1951.txt",
|
||||
"rfc1952.txt",
|
||||
// exclude files from lib/std/compress/deflate/testdata
|
||||
".expect",
|
||||
".expect-noinput",
|
||||
".golden",
|
||||
".input",
|
||||
"compress-e.txt",
|
||||
"compress-gettysburg.txt",
|
||||
"compress-pi.txt",
|
||||
"rfc1951.txt",
|
||||
// exclude files from lib/std/tz/
|
||||
".tzif",
|
||||
// others
|
||||
"README.md",
|
||||
},
|
||||
.blank_extensions = &[_][]const u8{
|
||||
"test.zig",
|
||||
},
|
||||
});
|
||||
|
||||
const tracy = b.option([]const u8, "tracy", "Enable Tracy integration. Supply path to Tracy source");
|
||||
const tracy_callstack = b.option(bool, "tracy-callstack", "Include callstack information with Tracy data. Does nothing if -Dtracy is not provided") orelse false;
|
||||
const tracy_allocation = b.option(bool, "tracy-allocation", "Include allocation information with Tracy data. Does nothing if -Dtracy is not provided") orelse false;
|
||||
const force_gpa = b.option(bool, "force-gpa", "Force the compiler to use GeneralPurposeAllocator") orelse false;
|
||||
const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm;
|
||||
const strip = b.option(bool, "strip", "Omit debug information") orelse false;
|
||||
const value_tracing = b.option(bool, "value-tracing", "Enable extra state tracking to help troubleshoot bugs in the compiler (using the std.debug.Trace API)") orelse false;
|
||||
|
||||
const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: {
|
||||
if (strip) break :blk @as(u32, 0);
|
||||
if (mode != .Debug) break :blk 0;
|
||||
break :blk 4;
|
||||
};
|
||||
|
||||
const main_file: ?[]const u8 = if (is_stage1) null else "src/main.zig";
|
||||
|
||||
const exe = b.addExecutable("zig", main_file);
|
||||
exe.strip = strip;
|
||||
exe.install();
|
||||
exe.setBuildMode(mode);
|
||||
exe.setTarget(target);
|
||||
|
||||
b.default_step.dependOn(&exe.step);
|
||||
exe.single_threaded = single_threaded;
|
||||
|
||||
if (target.isWindows() and target.getAbi() == .gnu) {
|
||||
// LTO is currently broken on mingw, this can be removed when it's fixed.
|
||||
exe.want_lto = false;
|
||||
}
|
||||
|
||||
const exe_options = b.addOptions();
|
||||
exe.addOptions("build_options", exe_options);
|
||||
|
||||
exe_options.addOption(u32, "mem_leak_frames", mem_leak_frames);
|
||||
exe_options.addOption(bool, "skip_non_native", false);
|
||||
exe_options.addOption(bool, "have_llvm", enable_llvm);
|
||||
exe_options.addOption(bool, "llvm_has_m68k", llvm_has_m68k);
|
||||
exe_options.addOption(bool, "llvm_has_csky", llvm_has_csky);
|
||||
exe_options.addOption(bool, "llvm_has_ve", llvm_has_ve);
|
||||
exe_options.addOption(bool, "llvm_has_arc", llvm_has_arc);
|
||||
exe_options.addOption(bool, "force_gpa", force_gpa);
|
||||
|
||||
if (link_libc) {
|
||||
exe.linkLibC();
|
||||
}
|
||||
|
||||
const is_debug = mode == .Debug;
|
||||
const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug;
|
||||
const enable_link_snapshots = b.option(bool, "link-snapshot", "Whether to enable linker state snapshots") orelse false;
|
||||
|
||||
const opt_version_string = b.option([]const u8, "version-string", "Override Zig version string. Default is to find out with git.");
|
||||
const version = if (opt_version_string) |version| version else v: {
|
||||
const version_string = b.fmt("{d}.{d}.{d}", .{ zig_version.major, zig_version.minor, zig_version.patch });
|
||||
|
||||
var code: u8 = undefined;
|
||||
const git_describe_untrimmed = b.execAllowFail(&[_][]const u8{
|
||||
"git", "-C", b.build_root, "describe", "--match", "*.*.*", "--tags",
|
||||
}, &code, .Ignore) catch {
|
||||
break :v version_string;
|
||||
};
|
||||
const git_describe = mem.trim(u8, git_describe_untrimmed, " \n\r");
|
||||
|
||||
switch (mem.count(u8, git_describe, "-")) {
|
||||
0 => {
|
||||
// Tagged release version (e.g. 0.9.0).
|
||||
if (!mem.eql(u8, git_describe, version_string)) {
|
||||
std.debug.print("Zig version '{s}' does not match Git tag '{s}'\n", .{ version_string, git_describe });
|
||||
std.process.exit(1);
|
||||
}
|
||||
break :v version_string;
|
||||
},
|
||||
2 => {
|
||||
// Untagged development build (e.g. 0.9.0-dev.2025+ecf0050a9).
|
||||
var it = mem.split(u8, git_describe, "-");
|
||||
const tagged_ancestor = it.next() orelse unreachable;
|
||||
const commit_height = it.next() orelse unreachable;
|
||||
const commit_id = it.next() orelse unreachable;
|
||||
|
||||
const ancestor_ver = try std.builtin.Version.parse(tagged_ancestor);
|
||||
if (zig_version.order(ancestor_ver) != .gt) {
|
||||
std.debug.print("Zig version '{}' must be greater than tagged ancestor '{}'\n", .{ zig_version, ancestor_ver });
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
// Check that the commit hash is prefixed with a 'g' (a Git convention).
|
||||
if (commit_id.len < 1 or commit_id[0] != 'g') {
|
||||
std.debug.print("Unexpected `git describe` output: {s}\n", .{git_describe});
|
||||
break :v version_string;
|
||||
}
|
||||
|
||||
// The version is reformatted in accordance with the https://semver.org specification.
|
||||
break :v b.fmt("{s}-dev.{s}+{s}", .{ version_string, commit_height, commit_id[1..] });
|
||||
},
|
||||
else => {
|
||||
std.debug.print("Unexpected `git describe` output: {s}\n", .{git_describe});
|
||||
break :v version_string;
|
||||
},
|
||||
}
|
||||
};
|
||||
exe_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version));
|
||||
|
||||
if (enable_llvm) {
|
||||
const cmake_cfg = if (static_llvm) null else findAndParseConfigH(b, config_h_path_option);
|
||||
|
||||
if (is_stage1) {
|
||||
const softfloat = b.addStaticLibrary("softfloat", null);
|
||||
softfloat.setBuildMode(.ReleaseFast);
|
||||
softfloat.setTarget(target);
|
||||
softfloat.addIncludeDir("deps/SoftFloat-3e-prebuilt");
|
||||
softfloat.addIncludeDir("deps/SoftFloat-3e/source/8086");
|
||||
softfloat.addIncludeDir("deps/SoftFloat-3e/source/include");
|
||||
softfloat.addCSourceFiles(&softfloat_sources, &[_][]const u8{ "-std=c99", "-O3" });
|
||||
softfloat.single_threaded = single_threaded;
|
||||
|
||||
const zig0 = b.addExecutable("zig0", null);
|
||||
zig0.addCSourceFiles(&.{"src/stage1/zig0.cpp"}, &exe_cflags);
|
||||
zig0.addIncludeDir("zig-cache/tmp"); // for config.h
|
||||
zig0.defineCMacro("ZIG_VERSION_MAJOR", b.fmt("{d}", .{zig_version.major}));
|
||||
zig0.defineCMacro("ZIG_VERSION_MINOR", b.fmt("{d}", .{zig_version.minor}));
|
||||
zig0.defineCMacro("ZIG_VERSION_PATCH", b.fmt("{d}", .{zig_version.patch}));
|
||||
zig0.defineCMacro("ZIG_VERSION_STRING", b.fmt("\"{s}\"", .{version}));
|
||||
|
||||
for ([_]*std.build.LibExeObjStep{ zig0, exe }) |artifact| {
|
||||
artifact.addIncludeDir("src");
|
||||
artifact.addIncludeDir("deps/SoftFloat-3e/source/include");
|
||||
artifact.addIncludeDir("deps/SoftFloat-3e-prebuilt");
|
||||
|
||||
artifact.defineCMacro("ZIG_LINK_MODE", "Static");
|
||||
|
||||
artifact.addCSourceFiles(&stage1_sources, &exe_cflags);
|
||||
artifact.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" });
|
||||
|
||||
artifact.linkLibrary(softfloat);
|
||||
artifact.linkLibCpp();
|
||||
}
|
||||
|
||||
try addStaticLlvmOptionsToExe(zig0);
|
||||
|
||||
const zig1_obj_ext = target.getObjectFormat().fileExt(target.getCpuArch());
|
||||
const zig1_obj_path = b.pathJoin(&.{ "zig-cache", "tmp", b.fmt("zig1{s}", .{zig1_obj_ext}) });
|
||||
const zig1_compiler_rt_path = b.pathJoin(&.{ b.pathFromRoot("lib"), "std", "special", "compiler_rt.zig" });
|
||||
|
||||
const zig1_obj = zig0.run();
|
||||
zig1_obj.addArgs(&.{
|
||||
"src/stage1.zig",
|
||||
"-target",
|
||||
try target.zigTriple(b.allocator),
|
||||
"-mcpu=baseline",
|
||||
"--name",
|
||||
"zig1",
|
||||
"--zig-lib-dir",
|
||||
b.pathFromRoot("lib"),
|
||||
b.fmt("-femit-bin={s}", .{b.pathFromRoot(zig1_obj_path)}),
|
||||
"-fcompiler-rt",
|
||||
"-lc",
|
||||
});
|
||||
{
|
||||
zig1_obj.addArgs(&.{ "--pkg-begin", "build_options" });
|
||||
zig1_obj.addFileSourceArg(exe_options.getSource());
|
||||
zig1_obj.addArgs(&.{ "--pkg-end", "--pkg-begin", "compiler_rt", zig1_compiler_rt_path, "--pkg-end" });
|
||||
}
|
||||
switch (mode) {
|
||||
.Debug => {},
|
||||
.ReleaseFast => {
|
||||
zig1_obj.addArg("-OReleaseFast");
|
||||
zig1_obj.addArg("--strip");
|
||||
},
|
||||
.ReleaseSafe => {
|
||||
zig1_obj.addArg("-OReleaseSafe");
|
||||
zig1_obj.addArg("--strip");
|
||||
},
|
||||
.ReleaseSmall => {
|
||||
zig1_obj.addArg("-OReleaseSmall");
|
||||
zig1_obj.addArg("--strip");
|
||||
},
|
||||
}
|
||||
if (single_threaded orelse false) {
|
||||
zig1_obj.addArg("-fsingle-threaded");
|
||||
}
|
||||
|
||||
exe.step.dependOn(&zig1_obj.step);
|
||||
exe.addObjectFile(zig1_obj_path);
|
||||
|
||||
// This is intentionally a dummy path. stage1.zig tries to @import("compiler_rt") in case
|
||||
// of being built by cmake. But when built by zig it's gonna get a compiler_rt so that
|
||||
// is pointless.
|
||||
exe.addPackagePath("compiler_rt", "src/empty.zig");
|
||||
}
|
||||
if (cmake_cfg) |cfg| {
|
||||
// Inside this code path, we have to coordinate with system packaged LLVM, Clang, and LLD.
|
||||
// That means we also have to rely on stage1 compiled c++ files. We parse config.h to find
|
||||
// the information passed on to us from cmake.
|
||||
if (cfg.cmake_prefix_path.len > 0) {
|
||||
b.addSearchPrefix(cfg.cmake_prefix_path);
|
||||
}
|
||||
|
||||
try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx);
|
||||
} else {
|
||||
// Here we are -Denable-llvm but no cmake integration.
|
||||
try addStaticLlvmOptionsToExe(exe);
|
||||
}
|
||||
}
|
||||
|
||||
const semver = try std.SemanticVersion.parse(version);
|
||||
exe_options.addOption(std.SemanticVersion, "semver", semver);
|
||||
|
||||
exe_options.addOption(bool, "enable_logging", enable_logging);
|
||||
exe_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
|
||||
exe_options.addOption(bool, "enable_tracy", tracy != null);
|
||||
exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);
|
||||
exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);
|
||||
exe_options.addOption(bool, "value_tracing", value_tracing);
|
||||
exe_options.addOption(bool, "is_stage1", is_stage1);
|
||||
exe_options.addOption(bool, "omit_stage2", omit_stage2);
|
||||
if (tracy) |tracy_path| {
|
||||
const client_cpp = fs.path.join(
|
||||
b.allocator,
|
||||
&[_][]const u8{ tracy_path, "TracyClient.cpp" },
|
||||
) catch unreachable;
|
||||
|
||||
// On mingw, we need to opt into windows 7+ to get some features required by tracy.
|
||||
const tracy_c_flags: []const []const u8 = if (target.isWindows() and target.getAbi() == .gnu)
|
||||
&[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined", "-D_WIN32_WINNT=0x601" }
|
||||
else
|
||||
&[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined" };
|
||||
|
||||
exe.addIncludeDir(tracy_path);
|
||||
exe.addCSourceFile(client_cpp, tracy_c_flags);
|
||||
if (!enable_llvm) {
|
||||
exe.linkSystemLibraryName("c++");
|
||||
}
|
||||
exe.linkLibC();
|
||||
|
||||
if (target.isWindows()) {
|
||||
exe.linkSystemLibrary("dbghelp");
|
||||
exe.linkSystemLibrary("ws2_32");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const exe_cflags = [_][]const u8{
|
||||
"-std=c++14",
|
||||
"-D__STDC_CONSTANT_MACROS",
|
||||
"-D__STDC_FORMAT_MACROS",
|
||||
"-D__STDC_LIMIT_MACROS",
|
||||
"-D_GNU_SOURCE",
|
||||
"-fvisibility-inlines-hidden",
|
||||
"-fno-exceptions",
|
||||
"-fno-rtti",
|
||||
"-Werror=type-limits",
|
||||
"-Wno-missing-braces",
|
||||
"-Wno-comment",
|
||||
};
|
||||
|
||||
fn addCmakeCfgOptionsToExe(
|
||||
b: *Builder,
|
||||
cfg: CMakeConfig,
|
||||
exe: *std.build.LibExeObjStep,
|
||||
use_zig_libcxx: bool,
|
||||
) !void {
|
||||
exe.addObjectFile(fs.path.join(b.allocator, &[_][]const u8{
|
||||
cfg.cmake_binary_dir,
|
||||
"zigcpp",
|
||||
b.fmt("{s}{s}{s}", .{ exe.target.libPrefix(), "zigcpp", exe.target.staticLibSuffix() }),
|
||||
}) catch unreachable);
|
||||
assert(cfg.lld_include_dir.len != 0);
|
||||
exe.addIncludeDir(cfg.lld_include_dir);
|
||||
addCMakeLibraryList(exe, cfg.clang_libraries);
|
||||
addCMakeLibraryList(exe, cfg.lld_libraries);
|
||||
addCMakeLibraryList(exe, cfg.llvm_libraries);
|
||||
|
||||
if (use_zig_libcxx) {
|
||||
exe.linkLibCpp();
|
||||
} else {
|
||||
const need_cpp_includes = true;
|
||||
|
||||
// System -lc++ must be used because in this code path we are attempting to link
|
||||
// against system-provided LLVM, Clang, LLD.
|
||||
if (exe.target.getOsTag() == .linux) {
|
||||
// First we try to static link against gcc libstdc++. If that doesn't work,
|
||||
// we fall back to -lc++ and cross our fingers.
|
||||
addCxxKnownPath(b, cfg, exe, "libstdc++.a", "", need_cpp_includes) catch |err| switch (err) {
|
||||
error.RequiredLibraryNotFound => {
|
||||
exe.linkSystemLibrary("c++");
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
exe.linkSystemLibrary("unwind");
|
||||
} else if (exe.target.isFreeBSD()) {
|
||||
try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes);
|
||||
exe.linkSystemLibrary("pthread");
|
||||
} else if (exe.target.getOsTag() == .openbsd) {
|
||||
try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes);
|
||||
try addCxxKnownPath(b, cfg, exe, "libc++abi.a", null, need_cpp_includes);
|
||||
} else if (exe.target.isDarwin()) {
|
||||
exe.linkSystemLibrary("c++");
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg.dia_guids_lib.len != 0) {
|
||||
exe.addObjectFile(cfg.dia_guids_lib);
|
||||
}
|
||||
}
|
||||
|
||||
fn addStaticLlvmOptionsToExe(
|
||||
exe: *std.build.LibExeObjStep,
|
||||
) !void {
|
||||
// Adds the Zig C++ sources which both stage1 and stage2 need.
|
||||
//
|
||||
// We need this because otherwise zig_clang_cc1_main.cpp ends up pulling
|
||||
// in a dependency on llvm::cfg::Update<llvm::BasicBlock*>::dump() which is
|
||||
// unavailable when LLVM is compiled in Release mode.
|
||||
const zig_cpp_cflags = exe_cflags ++ [_][]const u8{"-DNDEBUG=1"};
|
||||
exe.addCSourceFiles(&zig_cpp_sources, &zig_cpp_cflags);
|
||||
|
||||
for (clang_libs) |lib_name| {
|
||||
exe.linkSystemLibrary(lib_name);
|
||||
}
|
||||
|
||||
for (lld_libs) |lib_name| {
|
||||
exe.linkSystemLibrary(lib_name);
|
||||
}
|
||||
|
||||
for (llvm_libs) |lib_name| {
|
||||
exe.linkSystemLibrary(lib_name);
|
||||
}
|
||||
|
||||
exe.linkSystemLibrary("z");
|
||||
|
||||
// This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries.
|
||||
exe.linkSystemLibrary("c++");
|
||||
|
||||
if (exe.target.getOs().tag == .windows) {
|
||||
exe.linkSystemLibrary("version");
|
||||
exe.linkSystemLibrary("uuid");
|
||||
exe.linkSystemLibrary("ole32");
|
||||
}
|
||||
}
|
||||
|
||||
fn addCxxKnownPath(
|
||||
b: *Builder,
|
||||
ctx: CMakeConfig,
|
||||
exe: *std.build.LibExeObjStep,
|
||||
objname: []const u8,
|
||||
errtxt: ?[]const u8,
|
||||
need_cpp_includes: bool,
|
||||
) !void {
|
||||
const path_padded = try b.exec(&[_][]const u8{
|
||||
ctx.cxx_compiler,
|
||||
b.fmt("-print-file-name={s}", .{objname}),
|
||||
});
|
||||
const path_unpadded = mem.tokenize(u8, path_padded, "\r\n").next().?;
|
||||
if (mem.eql(u8, path_unpadded, objname)) {
|
||||
if (errtxt) |msg| {
|
||||
std.debug.print("{s}", .{msg});
|
||||
} else {
|
||||
std.debug.print("Unable to determine path to {s}\n", .{objname});
|
||||
}
|
||||
return error.RequiredLibraryNotFound;
|
||||
}
|
||||
exe.addObjectFile(path_unpadded);
|
||||
|
||||
// TODO a way to integrate with system c++ include files here
|
||||
// cc -E -Wp,-v -xc++ /dev/null
|
||||
if (need_cpp_includes) {
|
||||
// I used these temporarily for testing something but we obviously need a
|
||||
// more general purpose solution here.
|
||||
//exe.addIncludeDir("/nix/store/fvf3qjqa5qpcjjkq37pb6ypnk1mzhf5h-gcc-9.3.0/lib/gcc/x86_64-unknown-linux-gnu/9.3.0/../../../../include/c++/9.3.0");
|
||||
//exe.addIncludeDir("/nix/store/fvf3qjqa5qpcjjkq37pb6ypnk1mzhf5h-gcc-9.3.0/lib/gcc/x86_64-unknown-linux-gnu/9.3.0/../../../../include/c++/9.3.0/x86_64-unknown-linux-gnu");
|
||||
//exe.addIncludeDir("/nix/store/fvf3qjqa5qpcjjkq37pb6ypnk1mzhf5h-gcc-9.3.0/lib/gcc/x86_64-unknown-linux-gnu/9.3.0/../../../../include/c++/9.3.0/backward");
|
||||
}
|
||||
}
|
||||
|
||||
fn addCMakeLibraryList(exe: *std.build.LibExeObjStep, list: []const u8) void {
|
||||
var it = mem.tokenize(u8, list, ";");
|
||||
while (it.next()) |lib| {
|
||||
if (mem.startsWith(u8, lib, "-l")) {
|
||||
exe.linkSystemLibrary(lib["-l".len..]);
|
||||
} else {
|
||||
exe.addObjectFile(lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CMakeConfig = struct {
|
||||
cmake_binary_dir: []const u8,
|
||||
cmake_prefix_path: []const u8,
|
||||
cxx_compiler: []const u8,
|
||||
lld_include_dir: []const u8,
|
||||
lld_libraries: []const u8,
|
||||
clang_libraries: []const u8,
|
||||
llvm_libraries: []const u8,
|
||||
dia_guids_lib: []const u8,
|
||||
};
|
||||
|
||||
const max_config_h_bytes = 1 * 1024 * 1024;
|
||||
|
||||
fn findAndParseConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?CMakeConfig {
|
||||
const config_h_text: []const u8 = if (config_h_path_option) |config_h_path| blk: {
|
||||
break :blk fs.cwd().readFileAlloc(b.allocator, config_h_path, max_config_h_bytes) catch unreachable;
|
||||
} else blk: {
|
||||
// TODO this should stop looking for config.h once it detects we hit the
|
||||
// zig source root directory.
|
||||
var check_dir = fs.path.dirname(b.zig_exe).?;
|
||||
while (true) {
|
||||
var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable;
|
||||
defer dir.close();
|
||||
|
||||
break :blk dir.readFileAlloc(b.allocator, "config.h", max_config_h_bytes) catch |err| switch (err) {
|
||||
error.FileNotFound => {
|
||||
const new_check_dir = fs.path.dirname(check_dir);
|
||||
if (new_check_dir == null or mem.eql(u8, new_check_dir.?, check_dir)) {
|
||||
return null;
|
||||
}
|
||||
check_dir = new_check_dir.?;
|
||||
continue;
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
} else unreachable; // TODO should not need `else unreachable`.
|
||||
};
|
||||
|
||||
var ctx: CMakeConfig = .{
|
||||
.cmake_binary_dir = undefined,
|
||||
.cmake_prefix_path = undefined,
|
||||
.cxx_compiler = undefined,
|
||||
.lld_include_dir = undefined,
|
||||
.lld_libraries = undefined,
|
||||
.clang_libraries = undefined,
|
||||
.llvm_libraries = undefined,
|
||||
.dia_guids_lib = undefined,
|
||||
};
|
||||
|
||||
const mappings = [_]struct { prefix: []const u8, field: []const u8 }{
|
||||
.{
|
||||
.prefix = "#define ZIG_CMAKE_BINARY_DIR ",
|
||||
.field = "cmake_binary_dir",
|
||||
},
|
||||
.{
|
||||
.prefix = "#define ZIG_CMAKE_PREFIX_PATH ",
|
||||
.field = "cmake_prefix_path",
|
||||
},
|
||||
.{
|
||||
.prefix = "#define ZIG_CXX_COMPILER ",
|
||||
.field = "cxx_compiler",
|
||||
},
|
||||
.{
|
||||
.prefix = "#define ZIG_LLD_INCLUDE_PATH ",
|
||||
.field = "lld_include_dir",
|
||||
},
|
||||
.{
|
||||
.prefix = "#define ZIG_LLD_LIBRARIES ",
|
||||
.field = "lld_libraries",
|
||||
},
|
||||
.{
|
||||
.prefix = "#define ZIG_CLANG_LIBRARIES ",
|
||||
.field = "clang_libraries",
|
||||
},
|
||||
.{
|
||||
.prefix = "#define ZIG_LLVM_LIBRARIES ",
|
||||
.field = "llvm_libraries",
|
||||
},
|
||||
.{
|
||||
.prefix = "#define ZIG_DIA_GUIDS_LIB ",
|
||||
.field = "dia_guids_lib",
|
||||
},
|
||||
};
|
||||
|
||||
var lines_it = mem.tokenize(u8, config_h_text, "\r\n");
|
||||
while (lines_it.next()) |line| {
|
||||
inline for (mappings) |mapping| {
|
||||
if (mem.startsWith(u8, line, mapping.prefix)) {
|
||||
var it = mem.split(u8, line, "\"");
|
||||
_ = it.next().?; // skip the stuff before the quote
|
||||
const quoted = it.next().?; // the stuff inside the quote
|
||||
@field(ctx, mapping.field) = toNativePathSep(b, quoted);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
fn toNativePathSep(b: *Builder, s: []const u8) []u8 {
|
||||
const duplicated = b.allocator.dupe(u8, s) catch unreachable;
|
||||
for (duplicated) |*byte| switch (byte.*) {
|
||||
'/' => byte.* = fs.path.sep,
|
||||
else => {},
|
||||
};
|
||||
return duplicated;
|
||||
}
|
||||
|
||||
const softfloat_sources = [_][]const u8{
|
||||
"deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/extF80M_isSignalingNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_extF80MToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_propagateNaNExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c",
|
||||
"deps/SoftFloat-3e/source/f128M_add.c",
|
||||
"deps/SoftFloat-3e/source/f128M_div.c",
|
||||
"deps/SoftFloat-3e/source/f128M_eq.c",
|
||||
"deps/SoftFloat-3e/source/f128M_eq_signaling.c",
|
||||
"deps/SoftFloat-3e/source/f128M_le.c",
|
||||
"deps/SoftFloat-3e/source/f128M_le_quiet.c",
|
||||
"deps/SoftFloat-3e/source/f128M_lt.c",
|
||||
"deps/SoftFloat-3e/source/f128M_lt_quiet.c",
|
||||
"deps/SoftFloat-3e/source/f128M_mul.c",
|
||||
"deps/SoftFloat-3e/source/f128M_mulAdd.c",
|
||||
"deps/SoftFloat-3e/source/f128M_rem.c",
|
||||
"deps/SoftFloat-3e/source/f128M_roundToInt.c",
|
||||
"deps/SoftFloat-3e/source/f128M_sqrt.c",
|
||||
"deps/SoftFloat-3e/source/f128M_sub.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_f16.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_f32.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_f64.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_i32.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_i32_r_minMag.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_i64.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_i64_r_minMag.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_ui32.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_ui64.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_add.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_div.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_eq.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_le.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_lt.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_mul.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_rem.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_roundToInt.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_sqrt.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_sub.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f16.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f32.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f64.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f16_add.c",
|
||||
"deps/SoftFloat-3e/source/f16_div.c",
|
||||
"deps/SoftFloat-3e/source/f16_eq.c",
|
||||
"deps/SoftFloat-3e/source/f16_isSignalingNaN.c",
|
||||
"deps/SoftFloat-3e/source/f16_lt.c",
|
||||
"deps/SoftFloat-3e/source/f16_mul.c",
|
||||
"deps/SoftFloat-3e/source/f16_mulAdd.c",
|
||||
"deps/SoftFloat-3e/source/f16_rem.c",
|
||||
"deps/SoftFloat-3e/source/f16_roundToInt.c",
|
||||
"deps/SoftFloat-3e/source/f16_sqrt.c",
|
||||
"deps/SoftFloat-3e/source/f16_sub.c",
|
||||
"deps/SoftFloat-3e/source/f16_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f16_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f16_to_f64.c",
|
||||
"deps/SoftFloat-3e/source/f32_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f32_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f64_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f64_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f64_to_f16.c",
|
||||
"deps/SoftFloat-3e/source/i32_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/s_add256M.c",
|
||||
"deps/SoftFloat-3e/source/s_addCarryM.c",
|
||||
"deps/SoftFloat-3e/source/s_addComplCarryM.c",
|
||||
"deps/SoftFloat-3e/source/s_addF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_addExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_addM.c",
|
||||
"deps/SoftFloat-3e/source/s_addMagsF16.c",
|
||||
"deps/SoftFloat-3e/source/s_addMagsF32.c",
|
||||
"deps/SoftFloat-3e/source/s_addMagsF64.c",
|
||||
"deps/SoftFloat-3e/source/s_approxRecip32_1.c",
|
||||
"deps/SoftFloat-3e/source/s_approxRecipSqrt32_1.c",
|
||||
"deps/SoftFloat-3e/source/s_approxRecipSqrt_1Ks.c",
|
||||
"deps/SoftFloat-3e/source/s_approxRecip_1Ks.c",
|
||||
"deps/SoftFloat-3e/source/s_compare128M.c",
|
||||
"deps/SoftFloat-3e/source/s_compare96M.c",
|
||||
"deps/SoftFloat-3e/source/s_compareNonnormExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros16.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros32.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros64.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros8.c",
|
||||
"deps/SoftFloat-3e/source/s_eq128.c",
|
||||
"deps/SoftFloat-3e/source/s_invalidF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_invalidExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_isNaNF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_le128.c",
|
||||
"deps/SoftFloat-3e/source/s_lt128.c",
|
||||
"deps/SoftFloat-3e/source/s_mul128MTo256M.c",
|
||||
"deps/SoftFloat-3e/source/s_mul64To128M.c",
|
||||
"deps/SoftFloat-3e/source/s_mulAddF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_mulAddF16.c",
|
||||
"deps/SoftFloat-3e/source/s_mulAddF32.c",
|
||||
"deps/SoftFloat-3e/source/s_mulAddF64.c",
|
||||
"deps/SoftFloat-3e/source/s_negXM.c",
|
||||
"deps/SoftFloat-3e/source/s_normExtF80SigM.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackMToF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackMToExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackToF16.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackToF32.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackToF64.c",
|
||||
"deps/SoftFloat-3e/source/s_normSubnormalF128SigM.c",
|
||||
"deps/SoftFloat-3e/source/s_normSubnormalF16Sig.c",
|
||||
"deps/SoftFloat-3e/source/s_normSubnormalF32Sig.c",
|
||||
"deps/SoftFloat-3e/source/s_normSubnormalF64Sig.c",
|
||||
"deps/SoftFloat-3e/source/s_remStepMBy32.c",
|
||||
"deps/SoftFloat-3e/source/s_roundMToI64.c",
|
||||
"deps/SoftFloat-3e/source/s_roundMToUI64.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackMToExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackMToF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackToF16.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackToF32.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackToF64.c",
|
||||
"deps/SoftFloat-3e/source/s_roundToI32.c",
|
||||
"deps/SoftFloat-3e/source/s_roundToI64.c",
|
||||
"deps/SoftFloat-3e/source/s_roundToUI32.c",
|
||||
"deps/SoftFloat-3e/source/s_roundToUI64.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftLeftM.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftNormSigF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftRightJam256M.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftRightJam32.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftRightJam64.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftRightJamM.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftRightM.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftLeft64To96M.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftLeftM.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftRightExtendM.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftRightJam64.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftRightJamM.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftRightM.c",
|
||||
"deps/SoftFloat-3e/source/s_sub1XM.c",
|
||||
"deps/SoftFloat-3e/source/s_sub256M.c",
|
||||
"deps/SoftFloat-3e/source/s_subM.c",
|
||||
"deps/SoftFloat-3e/source/s_subMagsF16.c",
|
||||
"deps/SoftFloat-3e/source/s_subMagsF32.c",
|
||||
"deps/SoftFloat-3e/source/s_subMagsF64.c",
|
||||
"deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_tryPropagateNaNExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/softfloat_state.c",
|
||||
"deps/SoftFloat-3e/source/ui32_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/ui64_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/ui32_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/ui64_to_extF80M.c",
|
||||
};
|
||||
|
||||
const stage1_sources = [_][]const u8{
|
||||
"src/stage1/analyze.cpp",
|
||||
"src/stage1/astgen.cpp",
|
||||
"src/stage1/bigfloat.cpp",
|
||||
"src/stage1/bigint.cpp",
|
||||
"src/stage1/buffer.cpp",
|
||||
"src/stage1/codegen.cpp",
|
||||
"src/stage1/dump_analysis.cpp",
|
||||
"src/stage1/errmsg.cpp",
|
||||
"src/stage1/error.cpp",
|
||||
"src/stage1/heap.cpp",
|
||||
"src/stage1/ir.cpp",
|
||||
"src/stage1/ir_print.cpp",
|
||||
"src/stage1/mem.cpp",
|
||||
"src/stage1/os.cpp",
|
||||
"src/stage1/parser.cpp",
|
||||
"src/stage1/range_set.cpp",
|
||||
"src/stage1/stage1.cpp",
|
||||
"src/stage1/target.cpp",
|
||||
"src/stage1/tokenizer.cpp",
|
||||
"src/stage1/util.cpp",
|
||||
"src/stage1/softfloat_ext.cpp",
|
||||
};
|
||||
const optimized_c_sources = [_][]const u8{
|
||||
"src/stage1/parse_f128.c",
|
||||
};
|
||||
const zig_cpp_sources = [_][]const u8{
|
||||
// These are planned to stay even when we are self-hosted.
|
||||
"src/zig_llvm.cpp",
|
||||
"src/zig_clang.cpp",
|
||||
"src/zig_llvm-ar.cpp",
|
||||
"src/zig_clang_driver.cpp",
|
||||
"src/zig_clang_cc1_main.cpp",
|
||||
"src/zig_clang_cc1as_main.cpp",
|
||||
// https://github.com/ziglang/zig/issues/6363
|
||||
"src/windows_sdk.cpp",
|
||||
};
|
||||
|
||||
const clang_libs = [_][]const u8{
|
||||
"clangFrontendTool",
|
||||
"clangCodeGen",
|
||||
"clangFrontend",
|
||||
"clangDriver",
|
||||
"clangSerialization",
|
||||
"clangSema",
|
||||
"clangStaticAnalyzerFrontend",
|
||||
"clangStaticAnalyzerCheckers",
|
||||
"clangStaticAnalyzerCore",
|
||||
"clangAnalysis",
|
||||
"clangASTMatchers",
|
||||
"clangAST",
|
||||
"clangParse",
|
||||
"clangSema",
|
||||
"clangBasic",
|
||||
"clangEdit",
|
||||
"clangLex",
|
||||
"clangARCMigrate",
|
||||
"clangRewriteFrontend",
|
||||
"clangRewrite",
|
||||
"clangCrossTU",
|
||||
"clangIndex",
|
||||
"clangToolingCore",
|
||||
};
|
||||
const lld_libs = [_][]const u8{
|
||||
"lldDriver",
|
||||
"lldMinGW",
|
||||
"lldELF",
|
||||
"lldCOFF",
|
||||
"lldMachO",
|
||||
"lldWasm",
|
||||
"lldReaderWriter",
|
||||
"lldCore",
|
||||
"lldYAML",
|
||||
"lldCommon",
|
||||
};
|
||||
// This list can be re-generated with `llvm-config --libfiles` and then
|
||||
// reformatting using your favorite text editor. Note we do not execute
|
||||
// `llvm-config` here because we are cross compiling. Also omit LLVMTableGen
|
||||
// from these libs.
|
||||
const llvm_libs = [_][]const u8{
|
||||
"LLVMWindowsManifest",
|
||||
"LLVMXRay",
|
||||
"LLVMLibDriver",
|
||||
"LLVMDlltoolDriver",
|
||||
"LLVMCoverage",
|
||||
"LLVMLineEditor",
|
||||
"LLVMXCoreDisassembler",
|
||||
"LLVMXCoreCodeGen",
|
||||
"LLVMXCoreDesc",
|
||||
"LLVMXCoreInfo",
|
||||
"LLVMX86Disassembler",
|
||||
"LLVMX86AsmParser",
|
||||
"LLVMX86CodeGen",
|
||||
"LLVMX86Desc",
|
||||
"LLVMX86Info",
|
||||
"LLVMWebAssemblyDisassembler",
|
||||
"LLVMWebAssemblyAsmParser",
|
||||
"LLVMWebAssemblyCodeGen",
|
||||
"LLVMWebAssemblyDesc",
|
||||
"LLVMWebAssemblyUtils",
|
||||
"LLVMWebAssemblyInfo",
|
||||
"LLVMSystemZDisassembler",
|
||||
"LLVMSystemZAsmParser",
|
||||
"LLVMSystemZCodeGen",
|
||||
"LLVMSystemZDesc",
|
||||
"LLVMSystemZInfo",
|
||||
"LLVMSparcDisassembler",
|
||||
"LLVMSparcAsmParser",
|
||||
"LLVMSparcCodeGen",
|
||||
"LLVMSparcDesc",
|
||||
"LLVMSparcInfo",
|
||||
"LLVMRISCVDisassembler",
|
||||
"LLVMRISCVAsmParser",
|
||||
"LLVMRISCVCodeGen",
|
||||
"LLVMRISCVDesc",
|
||||
"LLVMRISCVInfo",
|
||||
"LLVMPowerPCDisassembler",
|
||||
"LLVMPowerPCAsmParser",
|
||||
"LLVMPowerPCCodeGen",
|
||||
"LLVMPowerPCDesc",
|
||||
"LLVMPowerPCInfo",
|
||||
"LLVMNVPTXCodeGen",
|
||||
"LLVMNVPTXDesc",
|
||||
"LLVMNVPTXInfo",
|
||||
"LLVMMSP430Disassembler",
|
||||
"LLVMMSP430AsmParser",
|
||||
"LLVMMSP430CodeGen",
|
||||
"LLVMMSP430Desc",
|
||||
"LLVMMSP430Info",
|
||||
"LLVMMipsDisassembler",
|
||||
"LLVMMipsAsmParser",
|
||||
"LLVMMipsCodeGen",
|
||||
"LLVMMipsDesc",
|
||||
"LLVMMipsInfo",
|
||||
"LLVMLanaiDisassembler",
|
||||
"LLVMLanaiCodeGen",
|
||||
"LLVMLanaiAsmParser",
|
||||
"LLVMLanaiDesc",
|
||||
"LLVMLanaiInfo",
|
||||
"LLVMHexagonDisassembler",
|
||||
"LLVMHexagonCodeGen",
|
||||
"LLVMHexagonAsmParser",
|
||||
"LLVMHexagonDesc",
|
||||
"LLVMHexagonInfo",
|
||||
"LLVMBPFDisassembler",
|
||||
"LLVMBPFAsmParser",
|
||||
"LLVMBPFCodeGen",
|
||||
"LLVMBPFDesc",
|
||||
"LLVMBPFInfo",
|
||||
"LLVMAVRDisassembler",
|
||||
"LLVMAVRAsmParser",
|
||||
"LLVMAVRCodeGen",
|
||||
"LLVMAVRDesc",
|
||||
"LLVMAVRInfo",
|
||||
"LLVMARMDisassembler",
|
||||
"LLVMARMAsmParser",
|
||||
"LLVMARMCodeGen",
|
||||
"LLVMARMDesc",
|
||||
"LLVMARMUtils",
|
||||
"LLVMARMInfo",
|
||||
"LLVMAMDGPUDisassembler",
|
||||
"LLVMAMDGPUAsmParser",
|
||||
"LLVMAMDGPUCodeGen",
|
||||
"LLVMAMDGPUDesc",
|
||||
"LLVMAMDGPUUtils",
|
||||
"LLVMAMDGPUInfo",
|
||||
"LLVMAArch64Disassembler",
|
||||
"LLVMAArch64AsmParser",
|
||||
"LLVMAArch64CodeGen",
|
||||
"LLVMAArch64Desc",
|
||||
"LLVMAArch64Utils",
|
||||
"LLVMAArch64Info",
|
||||
"LLVMOrcJIT",
|
||||
"LLVMMCJIT",
|
||||
"LLVMJITLink",
|
||||
"LLVMInterpreter",
|
||||
"LLVMExecutionEngine",
|
||||
"LLVMRuntimeDyld",
|
||||
"LLVMOrcTargetProcess",
|
||||
"LLVMOrcShared",
|
||||
"LLVMDWP",
|
||||
"LLVMSymbolize",
|
||||
"LLVMDebugInfoPDB",
|
||||
"LLVMDebugInfoGSYM",
|
||||
"LLVMOption",
|
||||
"LLVMObjectYAML",
|
||||
"LLVMMCA",
|
||||
"LLVMMCDisassembler",
|
||||
"LLVMLTO",
|
||||
"LLVMPasses",
|
||||
"LLVMCFGuard",
|
||||
"LLVMCoroutines",
|
||||
"LLVMObjCARCOpts",
|
||||
"LLVMipo",
|
||||
"LLVMVectorize",
|
||||
"LLVMLinker",
|
||||
"LLVMInstrumentation",
|
||||
"LLVMFrontendOpenMP",
|
||||
"LLVMFrontendOpenACC",
|
||||
"LLVMExtensions",
|
||||
"LLVMDWARFLinker",
|
||||
"LLVMGlobalISel",
|
||||
"LLVMMIRParser",
|
||||
"LLVMAsmPrinter",
|
||||
"LLVMDebugInfoMSF",
|
||||
"LLVMDebugInfoDWARF",
|
||||
"LLVMSelectionDAG",
|
||||
"LLVMCodeGen",
|
||||
"LLVMIRReader",
|
||||
"LLVMAsmParser",
|
||||
"LLVMInterfaceStub",
|
||||
"LLVMFileCheck",
|
||||
"LLVMFuzzMutate",
|
||||
"LLVMTarget",
|
||||
"LLVMScalarOpts",
|
||||
"LLVMInstCombine",
|
||||
"LLVMAggressiveInstCombine",
|
||||
"LLVMTransformUtils",
|
||||
"LLVMBitWriter",
|
||||
"LLVMAnalysis",
|
||||
"LLVMProfileData",
|
||||
"LLVMObject",
|
||||
"LLVMTextAPI",
|
||||
"LLVMMCParser",
|
||||
"LLVMMC",
|
||||
"LLVMDebugInfoCodeView",
|
||||
"LLVMBitReader",
|
||||
"LLVMCore",
|
||||
"LLVMRemarks",
|
||||
"LLVMBitstreamReader",
|
||||
"LLVMBinaryFormat",
|
||||
"LLVMSupport",
|
||||
"LLVMDemangle",
|
||||
};
|
||||
@ -8,15 +8,15 @@ brew update && brew install ncurses s3cmd
|
||||
ZIGDIR="$(pwd)"
|
||||
|
||||
HOST_ARCH="x86_64"
|
||||
HOST_TARGET="$HOST_ARCH-macos-gnu"
|
||||
HOST_TARGET="$HOST_ARCH-macos-none"
|
||||
HOST_MCPU="baseline"
|
||||
HOST_CACHE_BASENAME="zig+llvm+lld+clang-$HOST_TARGET-0.9.0-dev.1249+210ef5af8"
|
||||
HOST_CACHE_BASENAME="zig+llvm+lld+clang-$HOST_TARGET-0.10.0-dev.2348+d43761808"
|
||||
HOST_PREFIX="$HOME/$HOST_CACHE_BASENAME"
|
||||
|
||||
ARCH="aarch64"
|
||||
TARGET="$ARCH-macos-gnu"
|
||||
TARGET="$ARCH-macos-none"
|
||||
MCPU="apple_a14"
|
||||
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.9.0-dev.1249+210ef5af8"
|
||||
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.10.0-dev.2348+d43761808"
|
||||
PREFIX="$HOME/$CACHE_BASENAME"
|
||||
|
||||
JOBS="-j2"
|
||||
|
||||
@ -7,9 +7,9 @@ brew update && brew install ncurses s3cmd
|
||||
|
||||
ZIGDIR="$(pwd)"
|
||||
ARCH="x86_64"
|
||||
TARGET="$ARCH-macos-gnu"
|
||||
TARGET="$ARCH-macos-none"
|
||||
MCPU="baseline"
|
||||
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.9.0-dev.1249+210ef5af8"
|
||||
CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.10.0-dev.2348+d43761808"
|
||||
PREFIX="$HOME/$CACHE_BASENAME"
|
||||
JOBS="-j2"
|
||||
|
||||
@ -55,12 +55,28 @@ make $JOBS install
|
||||
cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig"
|
||||
make $JOBS install
|
||||
|
||||
# TODO figure out why this causes a segmentation fault
|
||||
# release/bin/zig test ../test/behavior.zig -fno-stage1 -fLLVM -I ../test
|
||||
# Build stage2 standalone so that we can test stage2 against stage2 compiler-rt.
|
||||
release/bin/zig build -p stage2 -Denable-llvm
|
||||
|
||||
release/bin/zig build test-toolchain -Denable-macos-sdk
|
||||
release/bin/zig build test-std
|
||||
release/bin/zig build docs
|
||||
stage2/bin/zig build test-behavior
|
||||
|
||||
# TODO: upgrade these to test stage2 instead of stage1
|
||||
# TODO: upgrade these to test stage3 instead of stage2
|
||||
release/bin/zig build test-behavior -Denable-macos-sdk -Domit-stage2
|
||||
release/bin/zig build test-compiler-rt -Denable-macos-sdk
|
||||
release/bin/zig build test-std -Denable-macos-sdk
|
||||
release/bin/zig build test-universal-libc -Denable-macos-sdk
|
||||
release/bin/zig build test-compare-output -Denable-macos-sdk
|
||||
release/bin/zig build test-standalone -Denable-macos-sdk
|
||||
release/bin/zig build test-stack-traces -Denable-macos-sdk
|
||||
release/bin/zig build test-cli -Denable-macos-sdk
|
||||
release/bin/zig build test-asm-link -Denable-macos-sdk
|
||||
release/bin/zig build test-translate-c -Denable-macos-sdk
|
||||
release/bin/zig build test-run-translated-c -Denable-macos-sdk
|
||||
release/bin/zig build docs -Denable-macos-sdk
|
||||
release/bin/zig build test-fmt -Denable-macos-sdk
|
||||
release/bin/zig build test-cases -Denable-macos-sdk -Dsingle-threaded
|
||||
release/bin/zig build test-link -Denable-macos-sdk
|
||||
|
||||
if [ "${BUILD_REASON}" != "PullRequest" ]; then
|
||||
mv ../LICENSE release/
|
||||
|
||||
@ -22,29 +22,149 @@ jobs:
|
||||
name: main
|
||||
displayName: 'Build'
|
||||
- job: BuildWindows
|
||||
timeoutInMinutes: 360
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
timeoutInMinutes: 360
|
||||
variables:
|
||||
TARGET: 'x86_64-windows-gnu'
|
||||
ZIG_LLVM_CLANG_LLD_NAME: 'zig+llvm+lld+clang-${{ variables.TARGET }}-0.9.1'
|
||||
ZIG_LLVM_CLANG_LLD_URL: 'https://ziglang.org/deps/${{ variables.ZIG_LLVM_CLANG_LLD_NAME }}.zip'
|
||||
steps:
|
||||
- powershell: |
|
||||
(New-Object Net.WebClient).DownloadFile("https://github.com/msys2/msys2-installer/releases/download/2022-01-28/msys2-base-x86_64-20220128.sfx.exe", "sfx.exe")
|
||||
.\sfx.exe -y -o\
|
||||
displayName: Download/Extract/Install MSYS2
|
||||
- script: |
|
||||
@REM install updated filesystem package first without dependency checking
|
||||
@REM because of: https://github.com/msys2/MSYS2-packages/issues/2021
|
||||
%CD:~0,2%\msys64\usr\bin\bash -lc "pacman --noconfirm -Sydd filesystem"
|
||||
displayName: Workaround filesystem dash MSYS2 dependency issue
|
||||
- script: |
|
||||
%CD:~0,2%\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
|
||||
%CD:~0,2%\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
|
||||
displayName: Update MSYS2
|
||||
- pwsh: |
|
||||
(New-Object Net.WebClient).DownloadFile("$(ZIG_LLVM_CLANG_LLD_URL)", "${ZIG_LLVM_CLANG_LLD_NAME}.zip")
|
||||
& 'C:\Program Files\7-Zip\7z.exe' x "${ZIG_LLVM_CLANG_LLD_NAME}.zip"
|
||||
name: install
|
||||
displayName: 'Install ZIG/LLVM/CLANG/LLD'
|
||||
|
||||
- pwsh: |
|
||||
Set-Variable -Name ZIGBUILDDIR -Value "$(Get-Location)\build"
|
||||
Set-Variable -Name ZIGINSTALLDIR -Value "${ZIGBUILDDIR}\dist"
|
||||
Set-Variable -Name ZIGPREFIXPATH -Value "$(Get-Location)\$(ZIG_LLVM_CLANG_LLD_NAME)"
|
||||
|
||||
# Make the `zig version` number consistent.
|
||||
# This will affect the `zig build` command below which uses `git describe`.
|
||||
git config core.abbrev 9
|
||||
git fetch --tags
|
||||
if ((git rev-parse --is-shallow-repository) -eq "true") {
|
||||
git fetch --unshallow # `git describe` won't work on a shallow repo
|
||||
}
|
||||
|
||||
# The dev kit zip file that we have here is old, and may be incompatible with
|
||||
# the build.zig script of master branch. So we keep an old version of build.zig
|
||||
# here in the CI directory.
|
||||
mv build.zig build.zig.master
|
||||
mv ci/azure/build.zig build.zig
|
||||
|
||||
mkdir $ZIGBUILDDIR
|
||||
cd $ZIGBUILDDIR
|
||||
|
||||
& "${ZIGPREFIXPATH}/bin/zig.exe" build `
|
||||
--prefix "$ZIGINSTALLDIR" `
|
||||
--search-prefix "$ZIGPREFIXPATH" `
|
||||
-Dstage1 `
|
||||
<# stage2 is omitted until we resolve https://github.com/ziglang/zig/issues/6485 #> `
|
||||
-Domit-stage2 `
|
||||
-Dstatic-llvm `
|
||||
-Drelease `
|
||||
-Dstrip `
|
||||
-Duse-zig-libcxx `
|
||||
-Dtarget=$(TARGET)
|
||||
|
||||
cd -
|
||||
|
||||
# Now that we have built an up-to-date zig.exe, we restore the original
|
||||
# build script from master branch.
|
||||
rm build.zig
|
||||
mv build.zig.master build.zig
|
||||
|
||||
name: build
|
||||
displayName: 'Build'
|
||||
|
||||
- pwsh: |
|
||||
Set-Variable -Name ZIGINSTALLDIR -Value "$(Get-Location)\build\dist"
|
||||
|
||||
# Sadly, stage2 is omitted from this build to save memory on the CI server. Once self-hosted is
|
||||
# built with itself and does not gobble as much memory, we can enable these tests.
|
||||
#& "$ZIGINSTALLDIR\bin\zig.exe" test "..\test\behavior.zig" -fno-stage1 -fLLVM -I "..\test" 2>&1
|
||||
|
||||
& "$ZIGINSTALLDIR\bin\zig.exe" build test-toolchain -Dskip-non-native -Dskip-stage2-tests 2>&1
|
||||
& "$ZIGINSTALLDIR\bin\zig.exe" build test-std -Dskip-non-native 2>&1
|
||||
name: test
|
||||
displayName: 'Test'
|
||||
|
||||
- pwsh: |
|
||||
Set-Variable -Name ZIGINSTALLDIR -Value "$(Get-Location)\build\dist"
|
||||
|
||||
& "$ZIGINSTALLDIR\bin\zig.exe" build docs
|
||||
timeoutInMinutes: 60
|
||||
name: doc
|
||||
displayName: 'Documentation'
|
||||
|
||||
- task: DownloadSecureFile@1
|
||||
inputs:
|
||||
secureFile: s3cfg
|
||||
- script: ci/azure/windows_msvc_script.bat
|
||||
name: main
|
||||
displayName: 'Build and test'
|
||||
name: aws_credentials
|
||||
secureFile: aws_credentials
|
||||
|
||||
- pwsh: |
|
||||
Set-Variable -Name ZIGBUILDDIR -Value "$(Get-Location)\build"
|
||||
$Env:AWS_SHARED_CREDENTIALS_FILE = "$Env:DOWNLOADSECUREFILE_SECUREFILEPATH"
|
||||
|
||||
# Workaround Azure networking issue
|
||||
# https://github.com/aws/aws-cli/issues/5749
|
||||
$Env:AWS_EC2_METADATA_DISABLED = "true"
|
||||
$Env:AWS_REGION = "us-west-2"
|
||||
|
||||
cd "$ZIGBUILDDIR"
|
||||
mv ../LICENSE dist/
|
||||
mv ../zig-cache/langref.html dist/
|
||||
mv dist/bin/zig.exe dist/
|
||||
rmdir dist/bin
|
||||
|
||||
# Remove the unnecessary zig dir in $prefix/lib/zig/std/std.zig
|
||||
mv dist/lib/zig dist/lib2
|
||||
rmdir dist/lib
|
||||
mv dist/lib2 dist/lib
|
||||
|
||||
Set-Variable -Name VERSION -Value $(./dist/zig.exe version)
|
||||
Set-Variable -Name DIRNAME -Value "zig-windows-x86_64-$VERSION"
|
||||
Set-Variable -Name TARBALL -Value "$DIRNAME.zip"
|
||||
mv dist "$DIRNAME"
|
||||
7z a "$TARBALL" "$DIRNAME"
|
||||
|
||||
aws s3 cp `
|
||||
"$TARBALL" `
|
||||
s3://ziglang.org/builds/ `
|
||||
--acl public-read `
|
||||
--cache-control 'public, max-age=31536000, immutable'
|
||||
|
||||
Set-Variable -Name SHASUM -Value (Get-FileHash "$TARBALL" -Algorithm SHA256 | select-object -ExpandProperty Hash).ToLower()
|
||||
Set-Variable -Name BYTESIZE -Value (Get-Item "$TARBALL").length
|
||||
|
||||
Set-Variable -Name JSONFILE -Value "windows-${Env:BUILD_SOURCEBRANCHNAME}.json"
|
||||
echo $null > $JSONFILE
|
||||
echo ('{"tarball": "' + $TARBALL + '",') >> $JSONFILE
|
||||
echo ('"shasum": "' + $SHASUM + '",') >> $JSONFILE
|
||||
echo ('"size": ' + $BYTESIZE + '}' ) >> $JSONFILE
|
||||
|
||||
aws s3 cp `
|
||||
"$JSONFILE" `
|
||||
s3://ziglang.org/builds/ `
|
||||
--acl public-read `
|
||||
--cache-control 'max-age=0, must-revalidate'
|
||||
|
||||
aws s3 cp `
|
||||
"$JSONFILE" `
|
||||
"s3://ziglang.org/builds/x86_64-windows-${VERSION}.json" `
|
||||
--acl public-read
|
||||
|
||||
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
|
||||
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
|
||||
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
|
||||
|
||||
name: upload
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
|
||||
displayName: 'Upload'
|
||||
|
||||
- job: OnMasterSuccess
|
||||
dependsOn:
|
||||
- BuildMacOS
|
||||
@ -54,7 +174,7 @@ jobs:
|
||||
strategy:
|
||||
maxParallel: 1
|
||||
pool:
|
||||
vmImage: 'ubuntu-18.04'
|
||||
vmImage: 'ubuntu-20.04'
|
||||
variables:
|
||||
version: $[ dependencies.BuildMacOS.outputs['main.version'] ]
|
||||
steps:
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
pacman -Suy --needed --noconfirm
|
||||
pacman -S --needed --noconfirm wget p7zip python3-pip tar xz
|
||||
|
||||
TARBALL="llvm+clang+lld-13.0.0-x86_64-windows-msvc-release-mt.tar.xz"
|
||||
|
||||
pip install s3cmd
|
||||
wget -nv "https://ziglang.org/deps/$TARBALL"
|
||||
# If the first extraction fails, re-try it once; this can happen if the tarball
|
||||
# contains symlinks that are in the table of contents before the files that
|
||||
# they point to.
|
||||
tar -xf $TARBALL || tar --overwrite -xf $TARBALL
|
||||
@ -1,39 +0,0 @@
|
||||
@echo on
|
||||
SET "SRCROOT=%cd%"
|
||||
SET "PREVPATH=%PATH%"
|
||||
SET "PREVMSYSTEM=%MSYSTEM%"
|
||||
|
||||
set "PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem"
|
||||
SET "MSYSTEM=MINGW64"
|
||||
bash -lc "cd ${SRCROOT} && ci/azure/windows_msvc_install" || exit /b
|
||||
SET "PATH=%PREVPATH%"
|
||||
SET "MSYSTEM=%PREVMSYSTEM%"
|
||||
|
||||
SET "ZIGBUILDDIR=%SRCROOT%\build"
|
||||
SET "ZIGINSTALLDIR=%ZIGBUILDDIR%\dist"
|
||||
SET "ZIGPREFIXPATH=%SRCROOT%\llvm+clang+lld-13.0.0-x86_64-windows-msvc-release-mt"
|
||||
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
|
||||
REM Make the `zig version` number consistent.
|
||||
REM This will affect the cmake command below.
|
||||
git.exe config core.abbrev 9
|
||||
git.exe fetch --unshallow
|
||||
git.exe fetch --tags
|
||||
|
||||
mkdir %ZIGBUILDDIR%
|
||||
cd %ZIGBUILDDIR%
|
||||
cmake.exe .. -Thost=x64 -G"Visual Studio 16 2019" -A x64 "-DCMAKE_INSTALL_PREFIX=%ZIGINSTALLDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release -DZIG_OMIT_STAGE2=ON || exit /b
|
||||
msbuild /maxcpucount /p:Configuration=Release INSTALL.vcxproj || exit /b
|
||||
|
||||
REM Sadly, stage2 is omitted from this build to save memory on the CI server. Once self-hosted is
|
||||
REM built with itself and does not gobble as much memory, we can enable these tests.
|
||||
REM "%ZIGINSTALLDIR%\bin\zig.exe" test "..\test\behavior.zig" -fno-stage1 -fLLVM -I "..\test" || exit /b
|
||||
|
||||
"%ZIGINSTALLDIR%\bin\zig.exe" build test-toolchain -Dskip-non-native -Dskip-stage2-tests || exit /b
|
||||
"%ZIGINSTALLDIR%\bin\zig.exe" build test-std -Dskip-non-native || exit /b
|
||||
"%ZIGINSTALLDIR%\bin\zig.exe" build docs || exit /b
|
||||
|
||||
set "PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem"
|
||||
SET "MSYSTEM=MINGW64"
|
||||
bash -lc "cd ${SRCROOT} && ci/azure/windows_upload" || exit /b
|
||||
@ -1,46 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
if [ "${BUILD_REASON}" != "PullRequest" ]; then
|
||||
cd "$ZIGBUILDDIR"
|
||||
|
||||
mv ../LICENSE dist/
|
||||
mv ../zig-cache/langref.html dist/
|
||||
mv dist/bin/zig.exe dist/
|
||||
rmdir dist/bin
|
||||
|
||||
# Remove the unnecessary zig dir in $prefix/lib/zig/std/std.zig
|
||||
mv dist/lib/zig dist/lib2
|
||||
rmdir dist/lib
|
||||
mv dist/lib2 dist/lib
|
||||
|
||||
VERSION=$(dist/zig.exe version)
|
||||
DIRNAME="zig-windows-x86_64-$VERSION"
|
||||
TARBALL="$DIRNAME.zip"
|
||||
mv dist "$DIRNAME"
|
||||
7z a "$TARBALL" "$DIRNAME"
|
||||
|
||||
# mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
|
||||
s3cmd -c "$DOWNLOADSECUREFILE_SECUREFILEPATH" put -P --add-header="cache-control: public, max-age=31536000, immutable" "$TARBALL" s3://ziglang.org/builds/
|
||||
|
||||
SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1)
|
||||
BYTESIZE=$(wc -c < $TARBALL)
|
||||
|
||||
JSONFILE="windows-$GITBRANCH.json"
|
||||
touch $JSONFILE
|
||||
echo "{\"tarball\": \"$TARBALL\"," >>$JSONFILE
|
||||
echo "\"shasum\": \"$SHASUM\"," >>$JSONFILE
|
||||
echo "\"size\": \"$BYTESIZE\"}" >>$JSONFILE
|
||||
|
||||
s3cmd -c "$DOWNLOADSECUREFILE_SECUREFILEPATH" put -P --add-header="Cache-Control: max-age=0, must-revalidate" "$JSONFILE" "s3://ziglang.org/builds/$JSONFILE"
|
||||
s3cmd -c "$DOWNLOADSECUREFILE_SECUREFILEPATH" put -P "$JSONFILE" "s3://ziglang.org/builds/x86_64-windows-$VERSION.json"
|
||||
|
||||
# `set -x` causes these variables to be mangled.
|
||||
# See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html
|
||||
set +x
|
||||
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
|
||||
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
|
||||
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
|
||||
fi
|
||||
@ -17,29 +17,28 @@ case "$1" in
|
||||
;;
|
||||
3)
|
||||
# ReleaseSafe
|
||||
./build/zig build $BUILD_FLAGS test-std -Dskip-debug -Dskip-release-fast -Dskip-release-small
|
||||
./build/zig build $BUILD_FLAGS test-std -Dskip-debug -Dskip-release-fast -Dskip-release-small -Dskip-non-native -Dskip-single-threaded
|
||||
;;
|
||||
4)
|
||||
# Releasefast
|
||||
./build/zig build $BUILD_FLAGS test-std -Dskip-debug -Dskip-release-safe -Dskip-release-small
|
||||
# ReleaseFast
|
||||
./build/zig build $BUILD_FLAGS test-std -Dskip-debug -Dskip-release-safe -Dskip-release-small -Dskip-non-native -Dskip-single-threaded
|
||||
;;
|
||||
5)
|
||||
# ReleaseSmall
|
||||
./build/zig build $BUILD_FLAGS test-std -Dskip-debug -Dskip-release-safe -Dskip-release-fast
|
||||
;;
|
||||
6)
|
||||
./build/zig build $BUILD_FLAGS test-minilibc
|
||||
./build/zig build $BUILD_FLAGS test-universal-libc
|
||||
./build/zig build $BUILD_FLAGS test-compare-output
|
||||
./build/zig build $BUILD_FLAGS test-standalone -Dskip-release-safe
|
||||
./build/zig build $BUILD_FLAGS test-stack-traces
|
||||
./build/zig build $BUILD_FLAGS test-cli
|
||||
./build/zig build $BUILD_FLAGS test-asm-link
|
||||
./build/zig build $BUILD_FLAGS test-runtime-safety
|
||||
./build/zig build $BUILD_FLAGS test-translate-c
|
||||
;;
|
||||
7)
|
||||
./build/zig build $BUILD_FLAGS # test building self-hosted without LLVM
|
||||
./build/zig build $BUILD_FLAGS test-stage2
|
||||
./build/zig build $BUILD_FLAGS test-cases
|
||||
;;
|
||||
'')
|
||||
echo "error: expecting test group argument"
|
||||
|
||||
@ -4,10 +4,10 @@ set -x
|
||||
set -e
|
||||
|
||||
sudo pkg update -fq
|
||||
sudo pkg install -y cmake py38-s3cmd wget curl jq samurai
|
||||
sudo pkg install -y cmake py39-s3cmd wget curl jq samurai
|
||||
|
||||
ZIGDIR="$(pwd)"
|
||||
CACHE_BASENAME="zig+llvm+lld+clang-x86_64-freebsd-gnu-0.9.0-dev.1243+456d7e5f5"
|
||||
CACHE_BASENAME="zig+llvm+lld+clang-x86_64-freebsd-gnu-0.9.1"
|
||||
PREFIX="$HOME/$CACHE_BASENAME"
|
||||
|
||||
cd $HOME
|
||||
@ -44,7 +44,7 @@ samu install
|
||||
#release/bin/zig test ../test/behavior.zig -fno-stage1 -fLLVM -I ../test
|
||||
|
||||
# Here we skip some tests to save time.
|
||||
release/bin/zig build test -Dskip-compile-errors -Dskip-non-native
|
||||
release/bin/zig build test -Dskip-stage1 -Dskip-non-native
|
||||
|
||||
if [ -f ~/.s3cfg ]; then
|
||||
mv ../LICENSE release/
|
||||
|
||||
@ -40,6 +40,77 @@
|
||||
"size": "{{AARCH64_LINUX_BYTESIZE}}"
|
||||
}
|
||||
},
|
||||
"0.9.1": {
|
||||
"date": "2022-02-14",
|
||||
"docs": "https://ziglang.org/documentation/0.9.1/",
|
||||
"stdDocs": "https://ziglang.org/documentation/0.9.1/std/",
|
||||
"notes": "https://ziglang.org/download/0.9.1/release-notes.html",
|
||||
"src": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-0.9.1.tar.xz",
|
||||
"shasum": "38cf4e84481f5facc766ba72783e7462e08d6d29a5d47e3b75c8ee3142485210",
|
||||
"size": "13940828"
|
||||
},
|
||||
"bootstrap": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-bootstrap-0.9.1.tar.xz",
|
||||
"shasum": "0a8e221c71860d8975c15662b3ed3bd863e81c4fe383455a596e5e0e490d6109",
|
||||
"size": "42488812"
|
||||
},
|
||||
"x86_64-freebsd": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-freebsd-x86_64-0.9.1.tar.xz",
|
||||
"shasum": "4e06009bd3ede34b72757eec1b5b291b30aa0d5046dadd16ecb6b34a02411254",
|
||||
"size": "39028848"
|
||||
},
|
||||
"aarch64-linux": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-linux-aarch64-0.9.1.tar.xz",
|
||||
"shasum": "5d99a39cded1870a3fa95d4de4ce68ac2610cca440336cfd252ffdddc2b90e66",
|
||||
"size": "37034860"
|
||||
},
|
||||
"armv7a-linux": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-linux-armv7a-0.9.1.tar.xz",
|
||||
"shasum": "6de64456cb4757a555816611ea697f86fba7681d8da3e1863fa726a417de49be",
|
||||
"size": "37974652"
|
||||
},
|
||||
"i386-linux": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-linux-i386-0.9.1.tar.xz",
|
||||
"shasum": "e776844fecd2e62fc40d94718891057a1dbca1816ff6013369e9a38c874374ca",
|
||||
"size": "44969172"
|
||||
},
|
||||
"riscv64-linux": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-linux-riscv64-0.9.1.tar.xz",
|
||||
"shasum": "208dea53662c2c52777bd9e3076115d2126a4f71aed7f2ff3b8fe224dc3881aa",
|
||||
"size": "39390868"
|
||||
},
|
||||
"x86_64-linux": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-linux-x86_64-0.9.1.tar.xz",
|
||||
"shasum": "be8da632c1d3273f766b69244d80669fe4f5e27798654681d77c992f17c237d7",
|
||||
"size": "41011464"
|
||||
},
|
||||
"aarch64-macos": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-macos-aarch64-0.9.1.tar.xz",
|
||||
"shasum": "8c473082b4f0f819f1da05de2dbd0c1e891dff7d85d2c12b6ee876887d438287",
|
||||
"size": "38995640"
|
||||
},
|
||||
"x86_64-macos": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-macos-x86_64-0.9.1.tar.xz",
|
||||
"shasum": "2d94984972d67292b55c1eb1c00de46580e9916575d083003546e9a01166754c",
|
||||
"size": "43713044"
|
||||
},
|
||||
"i386-windows": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-windows-i386-0.9.1.zip",
|
||||
"shasum": "74a640ed459914b96bcc572183a8db687bed0af08c30d2ea2f8eba03ae930f69",
|
||||
"size": "67929868"
|
||||
},
|
||||
"x86_64-windows": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-windows-x86_64-0.9.1.zip",
|
||||
"shasum": "443da53387d6ae8ba6bac4b3b90e9fef4ecbe545e1c5fa3a89485c36f5c0e3a2",
|
||||
"size": "65047697"
|
||||
},
|
||||
"aarch64-windows": {
|
||||
"tarball": "https://ziglang.org/download/0.9.1/zig-windows-aarch64-0.9.1.zip",
|
||||
"shasum": "621bf95f54dc3ff71466c5faae67479419951d7489e40e87fd26d195825fb842",
|
||||
"size": "61478151"
|
||||
}
|
||||
},
|
||||
"0.9.0": {
|
||||
"date": "2021-12-20",
|
||||
"docs": "https://ziglang.org/documentation/0.9.0/",
|
||||
|
||||
@ -57,7 +57,7 @@ unset CXX
|
||||
#release/bin/zig test ../test/behavior.zig -fno-stage1 -fLLVM -I ../test
|
||||
|
||||
# Here we skip some tests to save time.
|
||||
release/bin/zig build test -Dskip-compile-errors -Dskip-non-native
|
||||
release/bin/zig build test -Dskip-stage1 -Dskip-non-native
|
||||
|
||||
if [ -f ~/.s3cfg ]; then
|
||||
mv ../LICENSE release/
|
||||
|
||||
@ -9,20 +9,8 @@ workspace:
|
||||
path: /workspace
|
||||
|
||||
steps:
|
||||
- name: probe
|
||||
image: ci/debian-amd64:11.1-2
|
||||
commands:
|
||||
- ./ci/zinc/linux_probe.sh
|
||||
|
||||
- name: build
|
||||
image: ci/debian-amd64:11.1-2
|
||||
commands:
|
||||
- ./ci/zinc/linux_build.sh
|
||||
|
||||
- name: test
|
||||
depends_on:
|
||||
- build
|
||||
image: ci/debian-amd64:11.1-2
|
||||
image: ci/debian-amd64:11.1-3
|
||||
commands:
|
||||
- ./ci/zinc/linux_test.sh
|
||||
|
||||
@ -34,7 +22,7 @@ steps:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
image: ci/debian-amd64:11.1-2
|
||||
image: ci/debian-amd64:11.1-3
|
||||
environment:
|
||||
AWS_ACCESS_KEY_ID:
|
||||
from_secret: AWS_ACCESS_KEY_ID
|
||||
|
||||
@ -17,7 +17,6 @@ set -x
|
||||
set -e
|
||||
|
||||
ARCH="$(uname -m)"
|
||||
JOBS="-j$(nproc)"
|
||||
|
||||
DEPS_LOCAL="/deps/local"
|
||||
WORKSPACE="$DRONE_WORKSPACE"
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. ./ci/zinc/linux_base.sh
|
||||
|
||||
ZIG="$DEPS_LOCAL/bin/zig"
|
||||
TARGET="${ARCH}-linux-musl"
|
||||
MCPU="baseline"
|
||||
|
||||
# Make the `zig version` number consistent.
|
||||
# This will affect the cmake command below.
|
||||
git config core.abbrev 9
|
||||
|
||||
# Build debug zig.
|
||||
echo "BUILD debug zig with zig:$($ZIG version)"
|
||||
|
||||
export CC="$ZIG cc -target $TARGET -mcpu=$MCPU"
|
||||
export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU"
|
||||
|
||||
mkdir _debug
|
||||
cd _debug
|
||||
cmake .. \
|
||||
-DCMAKE_INSTALL_PREFIX="$DEBUG_STAGING" \
|
||||
-DCMAKE_PREFIX_PATH="$DEPS_LOCAL" \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DZIG_TARGET_TRIPLE="$TARGET" \
|
||||
-DZIG_TARGET_MCPU="$MCPU" \
|
||||
-DZIG_STATIC=ON \
|
||||
-GNinja
|
||||
|
||||
# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
|
||||
# so that installation and testing do not get affected by them.
|
||||
unset CC
|
||||
unset CXX
|
||||
|
||||
ninja $JOBS install
|
||||
|
||||
ZIG=$DEBUG_STAGING/bin/zig
|
||||
|
||||
# Here we rebuild zig but this time using the Zig binary we just now produced to
|
||||
# build zig1.o rather than relying on the one built with stage0. See
|
||||
# https://github.com/ziglang/zig/issues/6830 for more details.
|
||||
cmake .. -DZIG_EXECUTABLE="$ZIG"
|
||||
ninja $JOBS install
|
||||
|
||||
cd $WORKSPACE
|
||||
|
||||
# Build release zig.
|
||||
echo "BUILD release zig with zig:$($ZIG version)"
|
||||
export CC="$ZIG cc -target $TARGET -mcpu=$MCPU"
|
||||
export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU"
|
||||
mkdir _release
|
||||
cd _release
|
||||
cmake .. \
|
||||
-DCMAKE_INSTALL_PREFIX="$RELEASE_STAGING" \
|
||||
-DCMAKE_PREFIX_PATH="$DEPS_LOCAL" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DZIG_TARGET_TRIPLE="$TARGET" \
|
||||
-DZIG_TARGET_MCPU="$MCPU" \
|
||||
-DZIG_STATIC=ON \
|
||||
-GNinja
|
||||
unset CC
|
||||
unset CXX
|
||||
ninja $JOBS install
|
||||
|
||||
cd $WORKSPACE
|
||||
|
||||
# Look for non-conforming code formatting.
|
||||
# Formatting errors can be fixed by running `zig fmt` on the files printed here.
|
||||
$ZIG fmt --check .
|
||||
|
||||
# Explicit exit helps show last command duration.
|
||||
exit
|
||||
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. ./ci/zinc/linux_base.sh
|
||||
|
||||
# Probe CPU/brand details.
|
||||
echo "lscpu:"
|
||||
(lscpu | sed 's,^, : ,') 1>&2
|
||||
|
||||
# Explicit exit helps show last command duration.
|
||||
exit
|
||||
@ -2,34 +2,82 @@
|
||||
|
||||
. ./ci/zinc/linux_base.sh
|
||||
|
||||
ZIG=$DEBUG_STAGING/bin/zig
|
||||
ZIG="$DEPS_LOCAL/bin/zig"
|
||||
TARGET="${ARCH}-linux-musl"
|
||||
MCPU="baseline"
|
||||
|
||||
$ZIG test test/behavior.zig -fno-stage1 -I test -fLLVM
|
||||
$ZIG test test/behavior.zig -fno-stage1 -I test -ofmt=c
|
||||
$ZIG test test/behavior.zig -fno-stage1 -I test -target wasm32-wasi --test-cmd wasmtime --test-cmd-bin
|
||||
$ZIG test test/behavior.zig -fno-stage1 -I test -target arm-linux --test-cmd qemu-arm --test-cmd-bin
|
||||
$ZIG test test/behavior.zig -fno-stage1 -I test
|
||||
# Make the `zig version` number consistent.
|
||||
# This will affect the cmake command below.
|
||||
git config core.abbrev 9
|
||||
|
||||
$ZIG build test-behavior -fqemu -fwasmtime
|
||||
echo "BUILD debug zig with zig:$($ZIG version)"
|
||||
|
||||
export CC="$ZIG cc -target $TARGET -mcpu=$MCPU"
|
||||
export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU"
|
||||
|
||||
mkdir _debug
|
||||
cd _debug
|
||||
cmake .. \
|
||||
-DCMAKE_INSTALL_PREFIX="$DEBUG_STAGING" \
|
||||
-DCMAKE_PREFIX_PATH="$DEPS_LOCAL" \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DZIG_TARGET_TRIPLE="$TARGET" \
|
||||
-DZIG_TARGET_MCPU="$MCPU" \
|
||||
-DZIG_STATIC=ON \
|
||||
-GNinja
|
||||
|
||||
# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
|
||||
# so that installation and testing do not get affected by them.
|
||||
unset CC
|
||||
unset CXX
|
||||
|
||||
ninja install
|
||||
|
||||
ZIG="$DEBUG_STAGING/bin/zig"
|
||||
|
||||
# Here we rebuild zig but this time using the Zig binary we just now produced to
|
||||
# build zig1.o rather than relying on the one built with stage0. See
|
||||
# https://github.com/ziglang/zig/issues/6830 for more details.
|
||||
cmake .. -DZIG_EXECUTABLE="$ZIG"
|
||||
ninja install
|
||||
|
||||
cd $WORKSPACE
|
||||
|
||||
# Look for non-conforming code formatting.
|
||||
# Formatting errors can be fixed by running `zig fmt` on the files printed here.
|
||||
$ZIG fmt --check . --exclude test/cases/
|
||||
|
||||
# Build stage2 standalone so that we can test stage2 against stage2 compiler-rt.
|
||||
$ZIG build -p stage2 -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
|
||||
|
||||
# Ensure that stage2 can build itself.
|
||||
stage2/bin/zig build -p stage3 -Dstatic-llvm -Dtarget=native-native-musl --search-prefix "$DEPS_LOCAL"
|
||||
stage2/bin/zig build # test building self-hosted without LLVM
|
||||
stage2/bin/zig build -Dtarget=arm-linux-musleabihf # test building self-hosted for 32-bit arm
|
||||
|
||||
# Here we use stage2 instead of stage3 because of two bugs remaining:
|
||||
# * https://github.com/ziglang/zig/issues/11367 (and corresponding workaround in compiler source)
|
||||
# * https://github.com/ziglang/zig/pull/11492#issuecomment-1112871321
|
||||
stage2/bin/zig build test-behavior -fqemu -fwasmtime
|
||||
stage2/bin/zig test lib/std/std.zig --zig-lib-dir lib
|
||||
|
||||
$ZIG build test-behavior -fqemu -fwasmtime -Domit-stage2
|
||||
$ZIG build test-compiler-rt -fqemu -fwasmtime
|
||||
$ZIG build test-std -fqemu -fwasmtime
|
||||
$ZIG build test-minilibc -fqemu -fwasmtime
|
||||
$ZIG build test-universal-libc -fqemu -fwasmtime
|
||||
$ZIG build test-compare-output -fqemu -fwasmtime
|
||||
$ZIG build test-standalone -fqemu -fwasmtime
|
||||
$ZIG build test-stack-traces -fqemu -fwasmtime
|
||||
$ZIG build test-cli -fqemu -fwasmtime
|
||||
$ZIG build test-asm-link -fqemu -fwasmtime
|
||||
$ZIG build test-runtime-safety -fqemu -fwasmtime
|
||||
$ZIG build test-translate-c -fqemu -fwasmtime
|
||||
$ZIG build test-run-translated-c -fqemu -fwasmtime
|
||||
$ZIG build docs -fqemu -fwasmtime
|
||||
$ZIG build # test building self-hosted without LLVM
|
||||
$ZIG build -Dtarget=arm-linux-musleabihf # test building self-hosted for 32-bit arm
|
||||
$ZIG build test-fmt -fqemu -fwasmtime
|
||||
$ZIG build test-stage2 -fqemu -fwasmtime
|
||||
$ZIG build test-cases -fqemu -fwasmtime
|
||||
|
||||
# Produce the experimental std lib documentation.
|
||||
mkdir -p $RELEASE_STAGING/docs/std
|
||||
mkdir -p "$RELEASE_STAGING/docs/std"
|
||||
$ZIG test lib/std/std.zig \
|
||||
--zig-lib-dir lib \
|
||||
-femit-docs=$RELEASE_STAGING/docs/std \
|
||||
@ -38,5 +86,15 @@ $ZIG test lib/std/std.zig \
|
||||
# Look for HTML errors.
|
||||
tidy --drop-empty-elements no -qe zig-cache/langref.html
|
||||
|
||||
# Build release zig.
|
||||
$ZIG build \
|
||||
--prefix "$RELEASE_STAGING" \
|
||||
--search-prefix "$DEPS_LOCAL" \
|
||||
-Dstatic-llvm \
|
||||
-Drelease \
|
||||
-Dstrip \
|
||||
-Dtarget="$TARGET" \
|
||||
-Dstage1
|
||||
|
||||
# Explicit exit helps show last command duration.
|
||||
exit
|
||||
|
||||
@ -49,6 +49,7 @@ else()
|
||||
FIND_AND_ADD_LLD_LIB(lldELF)
|
||||
FIND_AND_ADD_LLD_LIB(lldCOFF)
|
||||
FIND_AND_ADD_LLD_LIB(lldWasm)
|
||||
FIND_AND_ADD_LLD_LIB(lldMachO)
|
||||
FIND_AND_ADD_LLD_LIB(lldReaderWriter)
|
||||
FIND_AND_ADD_LLD_LIB(lldCore)
|
||||
FIND_AND_ADD_LLD_LIB(lldYAML)
|
||||
|
||||
@ -12,6 +12,7 @@ find_path(LLVM_INCLUDE_DIRS NAMES llvm/IR/IRBuilder.h
|
||||
/usr/lib/llvm/14/include
|
||||
/usr/lib/llvm-14/include
|
||||
/usr/lib/llvm-14.0/include
|
||||
/usr/lib/llvm14/include
|
||||
/usr/local/llvm14/include
|
||||
/usr/local/llvm140/include
|
||||
/usr/local/opt/llvm@14/include
|
||||
@ -31,6 +32,7 @@ if(ZIG_PREFER_CLANG_CPP_DYLIB)
|
||||
/usr/lib/llvm/14/lib
|
||||
/usr/lib/llvm/14/lib64
|
||||
/usr/lib/llvm-14/lib
|
||||
/usr/lib/llvm14/lib
|
||||
/usr/local/llvm14/lib
|
||||
/usr/local/llvm140/lib
|
||||
/usr/local/opt/llvm@14/lib
|
||||
@ -181,19 +183,7 @@ else()
|
||||
|
||||
macro(FIND_AND_ADD_LLVM_LIB _libname_)
|
||||
string(TOUPPER ${_libname_} _prettylibname_)
|
||||
find_library(LLVM_${_prettylibname_}_LIB NAMES ${_libname_}
|
||||
PATHS
|
||||
${LLVM_LIBDIRS}
|
||||
/usr/lib/llvm/14/lib
|
||||
/usr/lib/llvm-14/lib
|
||||
/usr/lib/llvm-14.0/lib
|
||||
/usr/local/llvm140/lib
|
||||
/usr/local/llvm14/lib
|
||||
/usr/local/opt/llvm@14/lib
|
||||
/opt/homebrew/opt/llvm@14/lib
|
||||
/mingw64/lib
|
||||
/c/msys64/mingw64/lib
|
||||
c:\\msys64\\mingw64\\lib)
|
||||
find_library(LLVM_${_prettylibname_}_LIB NAMES ${_libname_} PATHS ${LLVM_LIBDIRS})
|
||||
set(LLVM_LIBRARIES ${LLVM_LIBRARIES} ${LLVM_${_prettylibname_}_LIB})
|
||||
endmacro(FIND_AND_ADD_LLVM_LIB)
|
||||
|
||||
|
||||
14
deps/SoftFloat-3e-prebuilt/platform.h
vendored
14
deps/SoftFloat-3e-prebuilt/platform.h
vendored
@ -17,8 +17,6 @@
|
||||
#define BIGENDIAN 1
|
||||
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define BIGENDIAN 1
|
||||
#elif defined(_BIG_ENDIAN)
|
||||
#define BIGENDIAN 1
|
||||
#elif defined(__sparc)
|
||||
#define BIGENDIAN 1
|
||||
#elif defined(__sparc__)
|
||||
@ -37,7 +35,9 @@
|
||||
#define BIGENDIAN 1
|
||||
#elif defined(__s390__)
|
||||
#define BIGENDIAN 1
|
||||
#elif defined(__LITTLE_ENDIAN__)
|
||||
#endif
|
||||
|
||||
#if defined(__LITTLE_ENDIAN__)
|
||||
#define LITTLEENDIAN 1
|
||||
#elif defined(__ARMEL__)
|
||||
#define LITTLEENDIAN 1
|
||||
@ -53,8 +53,6 @@
|
||||
#define LITTLEENDIAN 1
|
||||
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define LITTLEENDIAN 1
|
||||
#elif defined(_LITTLE_ENDIAN)
|
||||
#define LITTLEENDIAN 1
|
||||
#elif defined(__i386__)
|
||||
#define LITTLEENDIAN 1
|
||||
#elif defined(__alpha__)
|
||||
@ -83,7 +81,11 @@
|
||||
#define LITTLEENDIAN 1
|
||||
#elif defined(__bfin__)
|
||||
#define LITTLEENDIAN 1
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if defined(LITTLEENDIAN) && defined(BIGENDIAN)
|
||||
#error unable to detect endianness
|
||||
#elif !defined(LITTLEENDIAN) && !defined(BIGENDIAN)
|
||||
#error unable to detect endianness
|
||||
#endif
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef primitiveTypes_h
|
||||
#define primitiveTypes_h 1
|
||||
|
||||
#include "platform.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef SOFTFLOAT_FAST_INT64
|
||||
|
||||
@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef softfloat_types_h
|
||||
#define softfloat_types_h 1
|
||||
|
||||
#include "platform.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
||||
@ -1196,7 +1196,7 @@ fn genHtml(
|
||||
do_code_tests: bool,
|
||||
) !void {
|
||||
var progress = Progress{};
|
||||
const root_node = try progress.start("Generating docgen examples", toc.nodes.len);
|
||||
const root_node = progress.start("Generating docgen examples", toc.nodes.len);
|
||||
defer root_node.end();
|
||||
|
||||
var env_map = try process.getEnvMap(allocator);
|
||||
@ -1708,7 +1708,7 @@ fn genHtml(
|
||||
}
|
||||
}
|
||||
|
||||
fn exec(allocator: Allocator, env_map: *std.BufMap, args: []const []const u8) !ChildProcess.ExecResult {
|
||||
fn exec(allocator: Allocator, env_map: *process.EnvMap, args: []const []const u8) !ChildProcess.ExecResult {
|
||||
const result = try ChildProcess.exec(.{
|
||||
.allocator = allocator,
|
||||
.argv = args,
|
||||
@ -1732,7 +1732,7 @@ fn exec(allocator: Allocator, env_map: *std.BufMap, args: []const []const u8) !C
|
||||
return result;
|
||||
}
|
||||
|
||||
fn getBuiltinCode(allocator: Allocator, env_map: *std.BufMap, zig_exe: []const u8) ![]const u8 {
|
||||
fn getBuiltinCode(allocator: Allocator, env_map: *process.EnvMap, zig_exe: []const u8) ![]const u8 {
|
||||
const result = try exec(allocator, env_map, &[_][]const u8{ zig_exe, "build-obj", "--show-builtin" });
|
||||
return result.stdout;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -24,19 +24,19 @@ pub fn main() !void {
|
||||
var arg_idx: usize = 1;
|
||||
|
||||
const zig_exe = nextArg(args, &arg_idx) orelse {
|
||||
std.debug.print("Expected first argument to be path to zig compiler\n", .{});
|
||||
std.debug.print("Expected path to zig compiler\n", .{});
|
||||
return error.InvalidArgs;
|
||||
};
|
||||
const build_root = nextArg(args, &arg_idx) orelse {
|
||||
std.debug.print("Expected second argument to be build root directory path\n", .{});
|
||||
std.debug.print("Expected build root directory path\n", .{});
|
||||
return error.InvalidArgs;
|
||||
};
|
||||
const cache_root = nextArg(args, &arg_idx) orelse {
|
||||
std.debug.print("Expected third argument to be cache root directory path\n", .{});
|
||||
std.debug.print("Expected cache root directory path\n", .{});
|
||||
return error.InvalidArgs;
|
||||
};
|
||||
const global_cache_root = nextArg(args, &arg_idx) orelse {
|
||||
std.debug.print("Expected third argument to be global cache root directory path\n", .{});
|
||||
std.debug.print("Expected global cache root directory path\n", .{});
|
||||
return error.InvalidArgs;
|
||||
};
|
||||
|
||||
@ -147,10 +147,6 @@ pub fn main() !void {
|
||||
std.debug.print("Expected argument after --glibc-runtimes\n\n", .{});
|
||||
return usageAndErr(builder, false, stderr_stream);
|
||||
};
|
||||
} else if (mem.eql(u8, arg, "--verbose-tokenize")) {
|
||||
builder.verbose_tokenize = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-ast")) {
|
||||
builder.verbose_ast = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-link")) {
|
||||
builder.verbose_link = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-air")) {
|
||||
@ -185,6 +181,10 @@ pub fn main() !void {
|
||||
builder.enable_darling = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-darling")) {
|
||||
builder.enable_darling = false;
|
||||
} else if (mem.eql(u8, arg, "-fstage1")) {
|
||||
builder.use_stage1 = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-stage1")) {
|
||||
builder.use_stage1 = false;
|
||||
} else if (mem.eql(u8, arg, "--")) {
|
||||
builder.args = argsRest(args, arg_idx);
|
||||
break;
|
||||
@ -306,12 +306,13 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: anytype) !void
|
||||
try out_stream.writeAll(
|
||||
\\
|
||||
\\Advanced Options:
|
||||
\\ -fstage1 Force using bootstrap compiler as the codegen backend
|
||||
\\ -fno-stage1 Prevent using bootstrap compiler as the codegen backend
|
||||
\\ --build-file [file] Override path to build.zig
|
||||
\\ --cache-dir [path] Override path to zig cache directory
|
||||
\\ --cache-dir [path] Override path to local Zig cache directory
|
||||
\\ --global-cache-dir [path] Override path to global Zig cache directory
|
||||
\\ --zig-lib-dir [arg] Override path to Zig lib directory
|
||||
\\ --debug-log [scope] Enable debugging the compiler
|
||||
\\ --verbose-tokenize Enable compiler debug output for tokenization
|
||||
\\ --verbose-ast Enable compiler debug output for parsing into an AST
|
||||
\\ --verbose-link Enable compiler debug output for linking
|
||||
\\ --verbose-air Enable compiler debug output for Zig AIR
|
||||
\\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
|
||||
@ -1,11 +1,17 @@
|
||||
//! This is Zig's multi-target implementation of libc.
|
||||
//! When builtin.link_libc is true, we need to export all the functions and
|
||||
//! provide an entire C API.
|
||||
//! Otherwise, only the functions which LLVM generates calls to need to be generated,
|
||||
//! such as memcpy, memset, and some math functions.
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const maxInt = std.math.maxInt;
|
||||
const math = std.math;
|
||||
const isNan = std.math.isNan;
|
||||
const maxInt = std.math.maxInt;
|
||||
const native_os = builtin.os.tag;
|
||||
const native_arch = builtin.cpu.arch;
|
||||
const native_abi = builtin.abi;
|
||||
const native_os = builtin.os.tag;
|
||||
const long_double_is_f128 = builtin.target.longDoubleIsF128();
|
||||
|
||||
const is_wasm = switch (native_arch) {
|
||||
.wasm32, .wasm64 => true,
|
||||
@ -19,10 +25,23 @@ const is_freestanding = switch (native_os) {
|
||||
.freestanding => true,
|
||||
else => false,
|
||||
};
|
||||
|
||||
comptime {
|
||||
if (is_freestanding and is_wasm and builtin.link_libc) {
|
||||
@export(wasm_start, .{ .name = "_start", .linkage = .Strong });
|
||||
}
|
||||
|
||||
if (native_os == .linux) {
|
||||
@export(clone, .{ .name = "clone" });
|
||||
}
|
||||
|
||||
@export(memset, .{ .name = "memset", .linkage = .Strong });
|
||||
@export(__memset, .{ .name = "__memset", .linkage = .Strong });
|
||||
@export(memcpy, .{ .name = "memcpy", .linkage = .Strong });
|
||||
@export(memmove, .{ .name = "memmove", .linkage = .Strong });
|
||||
@export(memcmp, .{ .name = "memcmp", .linkage = .Strong });
|
||||
@export(bcmp, .{ .name = "bcmp", .linkage = .Strong });
|
||||
|
||||
if (builtin.link_libc) {
|
||||
@export(strcmp, .{ .name = "strcmp", .linkage = .Strong });
|
||||
@export(strncmp, .{ .name = "strncmp", .linkage = .Strong });
|
||||
@ -37,13 +56,137 @@ comptime {
|
||||
}
|
||||
}
|
||||
|
||||
var _fltused: c_int = 1;
|
||||
// Avoid dragging in the runtime safety mechanisms into this .o file,
|
||||
// unless we're trying to test this file.
|
||||
pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn {
|
||||
@setCold(true);
|
||||
_ = error_return_trace;
|
||||
if (builtin.is_test) {
|
||||
std.debug.panic("{s}", .{msg});
|
||||
}
|
||||
if (native_os != .freestanding and native_os != .other) {
|
||||
std.os.abort();
|
||||
}
|
||||
while (true) {}
|
||||
}
|
||||
|
||||
extern fn main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
|
||||
fn wasm_start() callconv(.C) void {
|
||||
_ = main(0, undefined);
|
||||
}
|
||||
|
||||
fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
if (len != 0) {
|
||||
var d = dest.?;
|
||||
var n = len;
|
||||
while (true) {
|
||||
d[0] = c;
|
||||
n -= 1;
|
||||
if (n == 0) break;
|
||||
d += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
fn __memset(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 {
|
||||
if (dest_n < n)
|
||||
@panic("buffer overflow");
|
||||
return memset(dest, c, n);
|
||||
}
|
||||
|
||||
fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
if (len != 0) {
|
||||
var d = dest.?;
|
||||
var s = src.?;
|
||||
var n = len;
|
||||
while (true) {
|
||||
d[0] = s[0];
|
||||
n -= 1;
|
||||
if (n == 0) break;
|
||||
d += 1;
|
||||
s += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.C) ?[*]u8 {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
if (@ptrToInt(dest) < @ptrToInt(src)) {
|
||||
var index: usize = 0;
|
||||
while (index != n) : (index += 1) {
|
||||
dest.?[index] = src.?[index];
|
||||
}
|
||||
} else {
|
||||
var index = n;
|
||||
while (index != 0) {
|
||||
index -= 1;
|
||||
dest.?[index] = src.?[index];
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
fn memcmp(vl: ?[*]const u8, vr: ?[*]const u8, n: usize) callconv(.C) c_int {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
var index: usize = 0;
|
||||
while (index != n) : (index += 1) {
|
||||
const compare_val = @bitCast(i8, vl.?[index] -% vr.?[index]);
|
||||
if (compare_val != 0) {
|
||||
return compare_val;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
test "memcmp" {
|
||||
const base_arr = &[_]u8{ 1, 1, 1 };
|
||||
const arr1 = &[_]u8{ 1, 1, 1 };
|
||||
const arr2 = &[_]u8{ 1, 0, 1 };
|
||||
const arr3 = &[_]u8{ 1, 2, 1 };
|
||||
|
||||
try std.testing.expect(memcmp(base_arr[0..], arr1[0..], base_arr.len) == 0);
|
||||
try std.testing.expect(memcmp(base_arr[0..], arr2[0..], base_arr.len) > 0);
|
||||
try std.testing.expect(memcmp(base_arr[0..], arr3[0..], base_arr.len) < 0);
|
||||
}
|
||||
|
||||
fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.C) c_int {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
var index: usize = 0;
|
||||
while (index != n) : (index += 1) {
|
||||
if (vl[index] != vr[index]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
test "bcmp" {
|
||||
const base_arr = &[_]u8{ 1, 1, 1 };
|
||||
const arr1 = &[_]u8{ 1, 1, 1 };
|
||||
const arr2 = &[_]u8{ 1, 0, 1 };
|
||||
const arr3 = &[_]u8{ 1, 2, 1 };
|
||||
|
||||
try std.testing.expect(bcmp(base_arr[0..], arr1[0..], base_arr.len) == 0);
|
||||
try std.testing.expect(bcmp(base_arr[0..], arr2[0..], base_arr.len) != 0);
|
||||
try std.testing.expect(bcmp(base_arr[0..], arr3[0..], base_arr.len) != 0);
|
||||
}
|
||||
|
||||
var _fltused: c_int = 1;
|
||||
|
||||
fn strcpy(dest: [*:0]u8, src: [*:0]const u8) callconv(.C) [*:0]u8 {
|
||||
var i: usize = 0;
|
||||
while (src[i] != 0) : (i += 1) {
|
||||
@ -161,106 +304,6 @@ test "strncmp" {
|
||||
try std.testing.expect(strncmp("\xff", "\x02", 1) == 253);
|
||||
}
|
||||
|
||||
export fn memset(dest: ?[*]u8, c: u8, n: usize) callconv(.C) ?[*]u8 {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
var index: usize = 0;
|
||||
while (index != n) : (index += 1)
|
||||
dest.?[index] = c;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
export fn __memset(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 {
|
||||
if (dest_n < n)
|
||||
@panic("buffer overflow");
|
||||
return memset(dest, c, n);
|
||||
}
|
||||
|
||||
export fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) callconv(.C) ?[*]u8 {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
var index: usize = 0;
|
||||
while (index != n) : (index += 1)
|
||||
dest.?[index] = src.?[index];
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
export fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.C) ?[*]u8 {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
if (@ptrToInt(dest) < @ptrToInt(src)) {
|
||||
var index: usize = 0;
|
||||
while (index != n) : (index += 1) {
|
||||
dest.?[index] = src.?[index];
|
||||
}
|
||||
} else {
|
||||
var index = n;
|
||||
while (index != 0) {
|
||||
index -= 1;
|
||||
dest.?[index] = src.?[index];
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
export fn memcmp(vl: ?[*]const u8, vr: ?[*]const u8, n: usize) callconv(.C) c_int {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
var index: usize = 0;
|
||||
while (index != n) : (index += 1) {
|
||||
const compare_val = @bitCast(i8, vl.?[index] -% vr.?[index]);
|
||||
if (compare_val != 0) {
|
||||
return compare_val;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
test "memcmp" {
|
||||
const base_arr = &[_]u8{ 1, 1, 1 };
|
||||
const arr1 = &[_]u8{ 1, 1, 1 };
|
||||
const arr2 = &[_]u8{ 1, 0, 1 };
|
||||
const arr3 = &[_]u8{ 1, 2, 1 };
|
||||
|
||||
try std.testing.expect(memcmp(base_arr[0..], arr1[0..], base_arr.len) == 0);
|
||||
try std.testing.expect(memcmp(base_arr[0..], arr2[0..], base_arr.len) > 0);
|
||||
try std.testing.expect(memcmp(base_arr[0..], arr3[0..], base_arr.len) < 0);
|
||||
}
|
||||
|
||||
export fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.C) c_int {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
var index: usize = 0;
|
||||
while (index != n) : (index += 1) {
|
||||
if (vl[index] != vr[index]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
test "bcmp" {
|
||||
const base_arr = &[_]u8{ 1, 1, 1 };
|
||||
const arr1 = &[_]u8{ 1, 1, 1 };
|
||||
const arr2 = &[_]u8{ 1, 0, 1 };
|
||||
const arr3 = &[_]u8{ 1, 2, 1 };
|
||||
|
||||
try std.testing.expect(bcmp(base_arr[0..], arr1[0..], base_arr.len) == 0);
|
||||
try std.testing.expect(bcmp(base_arr[0..], arr2[0..], base_arr.len) != 0);
|
||||
try std.testing.expect(bcmp(base_arr[0..], arr3[0..], base_arr.len) != 0);
|
||||
}
|
||||
|
||||
comptime {
|
||||
if (native_os == .linux) {
|
||||
@export(clone, .{ .name = "clone" });
|
||||
}
|
||||
}
|
||||
|
||||
// TODO we should be able to put this directly in std/linux/x86_64.zig but
|
||||
// it causes a segfault in release mode. this is a workaround of calling it
|
||||
// across .o file boundaries. fix comptime @ptrCast of nakedcc functions.
|
||||
@ -582,7 +625,7 @@ fn clone() callconv(.Naked) void {
|
||||
\\ sc
|
||||
);
|
||||
},
|
||||
.sparcv9 => {
|
||||
.sparc64 => {
|
||||
// __clone(func, stack, flags, arg, ptid, tls, ctid)
|
||||
// i0, i1, i2, i3, i4, i5, sp
|
||||
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
|
||||
@ -629,568 +672,3 @@ fn clone() callconv(.Naked) void {
|
||||
else => @compileError("Implement clone() for this arch."),
|
||||
}
|
||||
}
|
||||
|
||||
const math = std.math;
|
||||
|
||||
export fn fmodf(x: f32, y: f32) f32 {
|
||||
return generic_fmod(f32, x, y);
|
||||
}
|
||||
export fn fmod(x: f64, y: f64) f64 {
|
||||
return generic_fmod(f64, x, y);
|
||||
}
|
||||
|
||||
export fn ceilf(x: f32) f32 {
|
||||
return math.ceil(x);
|
||||
}
|
||||
export fn ceil(x: f64) f64 {
|
||||
return math.ceil(x);
|
||||
}
|
||||
export fn ceill(x: c_longdouble) c_longdouble {
|
||||
if (!long_double_is_f128) {
|
||||
@panic("TODO implement this");
|
||||
}
|
||||
return math.ceil(x);
|
||||
}
|
||||
|
||||
export fn fmaf(a: f32, b: f32, c: f32) f32 {
|
||||
return math.fma(f32, a, b, c);
|
||||
}
|
||||
|
||||
export fn fma(a: f64, b: f64, c: f64) f64 {
|
||||
return math.fma(f64, a, b, c);
|
||||
}
|
||||
export fn fmal(a: c_longdouble, b: c_longdouble, c: c_longdouble) c_longdouble {
|
||||
if (!long_double_is_f128) {
|
||||
@panic("TODO implement this");
|
||||
}
|
||||
return math.fma(c_longdouble, a, b, c);
|
||||
}
|
||||
|
||||
export fn sin(a: f64) f64 {
|
||||
return math.sin(a);
|
||||
}
|
||||
|
||||
export fn sinf(a: f32) f32 {
|
||||
return math.sin(a);
|
||||
}
|
||||
|
||||
export fn cos(a: f64) f64 {
|
||||
return math.cos(a);
|
||||
}
|
||||
|
||||
export fn cosf(a: f32) f32 {
|
||||
return math.cos(a);
|
||||
}
|
||||
|
||||
export fn sincos(a: f64, r_sin: *f64, r_cos: *f64) void {
|
||||
r_sin.* = math.sin(a);
|
||||
r_cos.* = math.cos(a);
|
||||
}
|
||||
|
||||
export fn sincosf(a: f32, r_sin: *f32, r_cos: *f32) void {
|
||||
r_sin.* = math.sin(a);
|
||||
r_cos.* = math.cos(a);
|
||||
}
|
||||
|
||||
export fn exp(a: f64) f64 {
|
||||
return math.exp(a);
|
||||
}
|
||||
|
||||
export fn expf(a: f32) f32 {
|
||||
return math.exp(a);
|
||||
}
|
||||
|
||||
export fn exp2(a: f64) f64 {
|
||||
return math.exp2(a);
|
||||
}
|
||||
|
||||
export fn exp2f(a: f32) f32 {
|
||||
return math.exp2(a);
|
||||
}
|
||||
|
||||
export fn log(a: f64) f64 {
|
||||
return math.ln(a);
|
||||
}
|
||||
|
||||
export fn logf(a: f32) f32 {
|
||||
return math.ln(a);
|
||||
}
|
||||
|
||||
export fn log2(a: f64) f64 {
|
||||
return math.log2(a);
|
||||
}
|
||||
|
||||
export fn log2f(a: f32) f32 {
|
||||
return math.log2(a);
|
||||
}
|
||||
|
||||
export fn log10(a: f64) f64 {
|
||||
return math.log10(a);
|
||||
}
|
||||
|
||||
export fn log10f(a: f32) f32 {
|
||||
return math.log10(a);
|
||||
}
|
||||
|
||||
export fn fabs(a: f64) f64 {
|
||||
return math.fabs(a);
|
||||
}
|
||||
|
||||
export fn fabsf(a: f32) f32 {
|
||||
return math.fabs(a);
|
||||
}
|
||||
|
||||
export fn trunc(a: f64) f64 {
|
||||
return math.trunc(a);
|
||||
}
|
||||
|
||||
export fn truncf(a: f32) f32 {
|
||||
return math.trunc(a);
|
||||
}
|
||||
|
||||
export fn truncl(a: c_longdouble) c_longdouble {
|
||||
if (!long_double_is_f128) {
|
||||
@panic("TODO implement this");
|
||||
}
|
||||
return math.trunc(a);
|
||||
}
|
||||
|
||||
export fn round(a: f64) f64 {
|
||||
return math.round(a);
|
||||
}
|
||||
|
||||
export fn roundf(a: f32) f32 {
|
||||
return math.round(a);
|
||||
}
|
||||
|
||||
fn generic_fmod(comptime T: type, x: T, y: T) T {
|
||||
@setRuntimeSafety(false);
|
||||
|
||||
const bits = @typeInfo(T).Float.bits;
|
||||
const uint = std.meta.Int(.unsigned, bits);
|
||||
const log2uint = math.Log2Int(uint);
|
||||
const digits = if (T == f32) 23 else 52;
|
||||
const exp_bits = if (T == f32) 9 else 12;
|
||||
const bits_minus_1 = bits - 1;
|
||||
const mask = if (T == f32) 0xff else 0x7ff;
|
||||
var ux = @bitCast(uint, x);
|
||||
var uy = @bitCast(uint, y);
|
||||
var ex = @intCast(i32, (ux >> digits) & mask);
|
||||
var ey = @intCast(i32, (uy >> digits) & mask);
|
||||
const sx = if (T == f32) @intCast(u32, ux & 0x80000000) else @intCast(i32, ux >> bits_minus_1);
|
||||
var i: uint = undefined;
|
||||
|
||||
if (uy << 1 == 0 or isNan(@bitCast(T, uy)) or ex == mask)
|
||||
return (x * y) / (x * y);
|
||||
|
||||
if (ux << 1 <= uy << 1) {
|
||||
if (ux << 1 == uy << 1)
|
||||
return 0 * x;
|
||||
return x;
|
||||
}
|
||||
|
||||
// normalize x and y
|
||||
if (ex == 0) {
|
||||
i = ux << exp_bits;
|
||||
while (i >> bits_minus_1 == 0) : ({
|
||||
ex -= 1;
|
||||
i <<= 1;
|
||||
}) {}
|
||||
ux <<= @intCast(log2uint, @bitCast(u32, -ex + 1));
|
||||
} else {
|
||||
ux &= maxInt(uint) >> exp_bits;
|
||||
ux |= 1 << digits;
|
||||
}
|
||||
if (ey == 0) {
|
||||
i = uy << exp_bits;
|
||||
while (i >> bits_minus_1 == 0) : ({
|
||||
ey -= 1;
|
||||
i <<= 1;
|
||||
}) {}
|
||||
uy <<= @intCast(log2uint, @bitCast(u32, -ey + 1));
|
||||
} else {
|
||||
uy &= maxInt(uint) >> exp_bits;
|
||||
uy |= 1 << digits;
|
||||
}
|
||||
|
||||
// x mod y
|
||||
while (ex > ey) : (ex -= 1) {
|
||||
i = ux -% uy;
|
||||
if (i >> bits_minus_1 == 0) {
|
||||
if (i == 0)
|
||||
return 0 * x;
|
||||
ux = i;
|
||||
}
|
||||
ux <<= 1;
|
||||
}
|
||||
i = ux -% uy;
|
||||
if (i >> bits_minus_1 == 0) {
|
||||
if (i == 0)
|
||||
return 0 * x;
|
||||
ux = i;
|
||||
}
|
||||
while (ux >> digits == 0) : ({
|
||||
ux <<= 1;
|
||||
ex -= 1;
|
||||
}) {}
|
||||
|
||||
// scale result up
|
||||
if (ex > 0) {
|
||||
ux -%= 1 << digits;
|
||||
ux |= @as(uint, @bitCast(u32, ex)) << digits;
|
||||
} else {
|
||||
ux >>= @intCast(log2uint, @bitCast(u32, -ex + 1));
|
||||
}
|
||||
if (T == f32) {
|
||||
ux |= sx;
|
||||
} else {
|
||||
ux |= @intCast(uint, sx) << bits_minus_1;
|
||||
}
|
||||
return @bitCast(T, ux);
|
||||
}
|
||||
|
||||
test "fmod, fmodf" {
|
||||
inline for ([_]type{ f32, f64 }) |T| {
|
||||
const nan_val = math.nan(T);
|
||||
const inf_val = math.inf(T);
|
||||
|
||||
try std.testing.expect(isNan(generic_fmod(T, nan_val, 1.0)));
|
||||
try std.testing.expect(isNan(generic_fmod(T, 1.0, nan_val)));
|
||||
try std.testing.expect(isNan(generic_fmod(T, inf_val, 1.0)));
|
||||
try std.testing.expect(isNan(generic_fmod(T, 0.0, 0.0)));
|
||||
try std.testing.expect(isNan(generic_fmod(T, 1.0, 0.0)));
|
||||
|
||||
try std.testing.expectEqual(@as(T, 0.0), generic_fmod(T, 0.0, 2.0));
|
||||
try std.testing.expectEqual(@as(T, -0.0), generic_fmod(T, -0.0, 2.0));
|
||||
|
||||
try std.testing.expectEqual(@as(T, -2.0), generic_fmod(T, -32.0, 10.0));
|
||||
try std.testing.expectEqual(@as(T, -2.0), generic_fmod(T, -32.0, -10.0));
|
||||
try std.testing.expectEqual(@as(T, 2.0), generic_fmod(T, 32.0, 10.0));
|
||||
try std.testing.expectEqual(@as(T, 2.0), generic_fmod(T, 32.0, -10.0));
|
||||
}
|
||||
}
|
||||
|
||||
fn generic_fmin(comptime T: type, x: T, y: T) T {
|
||||
if (isNan(x))
|
||||
return y;
|
||||
if (isNan(y))
|
||||
return x;
|
||||
return if (x < y) x else y;
|
||||
}
|
||||
|
||||
export fn fminf(x: f32, y: f32) callconv(.C) f32 {
|
||||
return generic_fmin(f32, x, y);
|
||||
}
|
||||
|
||||
export fn fmin(x: f64, y: f64) callconv(.C) f64 {
|
||||
return generic_fmin(f64, x, y);
|
||||
}
|
||||
|
||||
test "fmin, fminf" {
|
||||
inline for ([_]type{ f32, f64 }) |T| {
|
||||
const nan_val = math.nan(T);
|
||||
|
||||
try std.testing.expect(isNan(generic_fmin(T, nan_val, nan_val)));
|
||||
try std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, nan_val, 1.0));
|
||||
try std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, 1.0, nan_val));
|
||||
|
||||
try std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, 1.0, 10.0));
|
||||
try std.testing.expectEqual(@as(T, -1.0), generic_fmin(T, 1.0, -1.0));
|
||||
}
|
||||
}
|
||||
|
||||
fn generic_fmax(comptime T: type, x: T, y: T) T {
|
||||
if (isNan(x))
|
||||
return y;
|
||||
if (isNan(y))
|
||||
return x;
|
||||
return if (x < y) y else x;
|
||||
}
|
||||
|
||||
export fn fmaxf(x: f32, y: f32) callconv(.C) f32 {
|
||||
return generic_fmax(f32, x, y);
|
||||
}
|
||||
|
||||
export fn fmax(x: f64, y: f64) callconv(.C) f64 {
|
||||
return generic_fmax(f64, x, y);
|
||||
}
|
||||
|
||||
test "fmax, fmaxf" {
|
||||
inline for ([_]type{ f32, f64 }) |T| {
|
||||
const nan_val = math.nan(T);
|
||||
|
||||
try std.testing.expect(isNan(generic_fmax(T, nan_val, nan_val)));
|
||||
try std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, nan_val, 1.0));
|
||||
try std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, 1.0, nan_val));
|
||||
|
||||
try std.testing.expectEqual(@as(T, 10.0), generic_fmax(T, 1.0, 10.0));
|
||||
try std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, 1.0, -1.0));
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound
|
||||
// behaviour. Most intermediate i32 values are changed to u32 where appropriate but there are
|
||||
// potentially some edge cases remaining that are not handled in the same way.
|
||||
export fn sqrt(x: f64) f64 {
|
||||
const tiny: f64 = 1.0e-300;
|
||||
const sign: u32 = 0x80000000;
|
||||
const u = @bitCast(u64, x);
|
||||
|
||||
var ix0 = @intCast(u32, u >> 32);
|
||||
var ix1 = @intCast(u32, u & 0xFFFFFFFF);
|
||||
|
||||
// sqrt(nan) = nan, sqrt(+inf) = +inf, sqrt(-inf) = nan
|
||||
if (ix0 & 0x7FF00000 == 0x7FF00000) {
|
||||
return x * x + x;
|
||||
}
|
||||
|
||||
// sqrt(+-0) = +-0
|
||||
if (x == 0.0) {
|
||||
return x;
|
||||
}
|
||||
// sqrt(-ve) = snan
|
||||
if (ix0 & sign != 0) {
|
||||
return math.snan(f64);
|
||||
}
|
||||
|
||||
// normalize x
|
||||
var m = @intCast(i32, ix0 >> 20);
|
||||
if (m == 0) {
|
||||
// subnormal
|
||||
while (ix0 == 0) {
|
||||
m -= 21;
|
||||
ix0 |= ix1 >> 11;
|
||||
ix1 <<= 21;
|
||||
}
|
||||
|
||||
// subnormal
|
||||
var i: u32 = 0;
|
||||
while (ix0 & 0x00100000 == 0) : (i += 1) {
|
||||
ix0 <<= 1;
|
||||
}
|
||||
m -= @intCast(i32, i) - 1;
|
||||
ix0 |= ix1 >> @intCast(u5, 32 - i);
|
||||
ix1 <<= @intCast(u5, i);
|
||||
}
|
||||
|
||||
// unbias exponent
|
||||
m -= 1023;
|
||||
ix0 = (ix0 & 0x000FFFFF) | 0x00100000;
|
||||
if (m & 1 != 0) {
|
||||
ix0 += ix0 + (ix1 >> 31);
|
||||
ix1 = ix1 +% ix1;
|
||||
}
|
||||
m >>= 1;
|
||||
|
||||
// sqrt(x) bit by bit
|
||||
ix0 += ix0 + (ix1 >> 31);
|
||||
ix1 = ix1 +% ix1;
|
||||
|
||||
var q: u32 = 0;
|
||||
var q1: u32 = 0;
|
||||
var s0: u32 = 0;
|
||||
var s1: u32 = 0;
|
||||
var r: u32 = 0x00200000;
|
||||
var t: u32 = undefined;
|
||||
var t1: u32 = undefined;
|
||||
|
||||
while (r != 0) {
|
||||
t = s0 +% r;
|
||||
if (t <= ix0) {
|
||||
s0 = t + r;
|
||||
ix0 -= t;
|
||||
q += r;
|
||||
}
|
||||
ix0 = ix0 +% ix0 +% (ix1 >> 31);
|
||||
ix1 = ix1 +% ix1;
|
||||
r >>= 1;
|
||||
}
|
||||
|
||||
r = sign;
|
||||
while (r != 0) {
|
||||
t1 = s1 +% r;
|
||||
t = s0;
|
||||
if (t < ix0 or (t == ix0 and t1 <= ix1)) {
|
||||
s1 = t1 +% r;
|
||||
if (t1 & sign == sign and s1 & sign == 0) {
|
||||
s0 += 1;
|
||||
}
|
||||
ix0 -= t;
|
||||
if (ix1 < t1) {
|
||||
ix0 -= 1;
|
||||
}
|
||||
ix1 = ix1 -% t1;
|
||||
q1 += r;
|
||||
}
|
||||
ix0 = ix0 +% ix0 +% (ix1 >> 31);
|
||||
ix1 = ix1 +% ix1;
|
||||
r >>= 1;
|
||||
}
|
||||
|
||||
// rounding direction
|
||||
if (ix0 | ix1 != 0) {
|
||||
var z = 1.0 - tiny; // raise inexact
|
||||
if (z >= 1.0) {
|
||||
z = 1.0 + tiny;
|
||||
if (q1 == 0xFFFFFFFF) {
|
||||
q1 = 0;
|
||||
q += 1;
|
||||
} else if (z > 1.0) {
|
||||
if (q1 == 0xFFFFFFFE) {
|
||||
q += 1;
|
||||
}
|
||||
q1 += 2;
|
||||
} else {
|
||||
q1 += q1 & 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ix0 = (q >> 1) + 0x3FE00000;
|
||||
ix1 = q1 >> 1;
|
||||
if (q & 1 != 0) {
|
||||
ix1 |= 0x80000000;
|
||||
}
|
||||
|
||||
// NOTE: musl here appears to rely on signed twos-complement wraparound. +% has the same
|
||||
// behaviour at least.
|
||||
var iix0 = @intCast(i32, ix0);
|
||||
iix0 = iix0 +% (m << 20);
|
||||
|
||||
const uz = (@intCast(u64, iix0) << 32) | ix1;
|
||||
return @bitCast(f64, uz);
|
||||
}
|
||||
|
||||
test "sqrt" {
|
||||
const V = [_]f64{
|
||||
0.0,
|
||||
4.089288054930154,
|
||||
7.538757127071935,
|
||||
8.97780793672623,
|
||||
5.304443821913729,
|
||||
5.682408965311888,
|
||||
0.5846878579110049,
|
||||
3.650338664297043,
|
||||
0.3178091951800732,
|
||||
7.1505232436382835,
|
||||
3.6589165881946464,
|
||||
};
|
||||
|
||||
// Note that @sqrt will either generate the sqrt opcode (if supported by the
|
||||
// target ISA) or a call to `sqrtf` otherwise.
|
||||
for (V) |val|
|
||||
try std.testing.expectEqual(@sqrt(val), sqrt(val));
|
||||
}
|
||||
|
||||
test "sqrt special" {
|
||||
try std.testing.expect(std.math.isPositiveInf(sqrt(std.math.inf(f64))));
|
||||
try std.testing.expect(sqrt(0.0) == 0.0);
|
||||
try std.testing.expect(sqrt(-0.0) == -0.0);
|
||||
try std.testing.expect(isNan(sqrt(-1.0)));
|
||||
try std.testing.expect(isNan(sqrt(std.math.nan(f64))));
|
||||
}
|
||||
|
||||
export fn sqrtf(x: f32) f32 {
|
||||
const tiny: f32 = 1.0e-30;
|
||||
const sign: i32 = @bitCast(i32, @as(u32, 0x80000000));
|
||||
var ix: i32 = @bitCast(i32, x);
|
||||
|
||||
if ((ix & 0x7F800000) == 0x7F800000) {
|
||||
return x * x + x; // sqrt(nan) = nan, sqrt(+inf) = +inf, sqrt(-inf) = snan
|
||||
}
|
||||
|
||||
// zero
|
||||
if (ix <= 0) {
|
||||
if (ix & ~sign == 0) {
|
||||
return x; // sqrt (+-0) = +-0
|
||||
}
|
||||
if (ix < 0) {
|
||||
return math.snan(f32);
|
||||
}
|
||||
}
|
||||
|
||||
// normalize
|
||||
var m = ix >> 23;
|
||||
if (m == 0) {
|
||||
// subnormal
|
||||
var i: i32 = 0;
|
||||
while (ix & 0x00800000 == 0) : (i += 1) {
|
||||
ix <<= 1;
|
||||
}
|
||||
m -= i - 1;
|
||||
}
|
||||
|
||||
m -= 127; // unbias exponent
|
||||
ix = (ix & 0x007FFFFF) | 0x00800000;
|
||||
|
||||
if (m & 1 != 0) { // odd m, double x to even
|
||||
ix += ix;
|
||||
}
|
||||
|
||||
m >>= 1; // m = [m / 2]
|
||||
|
||||
// sqrt(x) bit by bit
|
||||
ix += ix;
|
||||
var q: i32 = 0; // q = sqrt(x)
|
||||
var s: i32 = 0;
|
||||
var r: i32 = 0x01000000; // r = moving bit right -> left
|
||||
|
||||
while (r != 0) {
|
||||
const t = s + r;
|
||||
if (t <= ix) {
|
||||
s = t + r;
|
||||
ix -= t;
|
||||
q += r;
|
||||
}
|
||||
ix += ix;
|
||||
r >>= 1;
|
||||
}
|
||||
|
||||
// floating add to find rounding direction
|
||||
if (ix != 0) {
|
||||
var z = 1.0 - tiny; // inexact
|
||||
if (z >= 1.0) {
|
||||
z = 1.0 + tiny;
|
||||
if (z > 1.0) {
|
||||
q += 2;
|
||||
} else {
|
||||
if (q & 1 != 0) {
|
||||
q += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ix = (q >> 1) + 0x3f000000;
|
||||
ix += m << 23;
|
||||
return @bitCast(f32, ix);
|
||||
}
|
||||
|
||||
test "sqrtf" {
|
||||
const V = [_]f32{
|
||||
0.0,
|
||||
4.089288054930154,
|
||||
7.538757127071935,
|
||||
8.97780793672623,
|
||||
5.304443821913729,
|
||||
5.682408965311888,
|
||||
0.5846878579110049,
|
||||
3.650338664297043,
|
||||
0.3178091951800732,
|
||||
7.1505232436382835,
|
||||
3.6589165881946464,
|
||||
};
|
||||
|
||||
// Note that @sqrt will either generate the sqrt opcode (if supported by the
|
||||
// target ISA) or a call to `sqrtf` otherwise.
|
||||
for (V) |val|
|
||||
try std.testing.expectEqual(@sqrt(val), sqrtf(val));
|
||||
}
|
||||
|
||||
test "sqrtf special" {
|
||||
try std.testing.expect(std.math.isPositiveInf(sqrtf(std.math.inf(f32))));
|
||||
try std.testing.expect(sqrtf(0.0) == 0.0);
|
||||
try std.testing.expect(sqrtf(-0.0) == -0.0);
|
||||
try std.testing.expect(isNan(sqrtf(-1.0)));
|
||||
try std.testing.expect(isNan(sqrtf(std.math.nan(f32))));
|
||||
}
|
||||
187
lib/compiler_rt.zig
Normal file
187
lib/compiler_rt.zig
Normal file
@ -0,0 +1,187 @@
|
||||
pub const panic = @import("compiler_rt/common.zig").panic;
|
||||
|
||||
comptime {
|
||||
_ = @import("compiler_rt/atomics.zig");
|
||||
|
||||
_ = @import("compiler_rt/addf3.zig");
|
||||
_ = @import("compiler_rt/addsf3.zig");
|
||||
_ = @import("compiler_rt/adddf3.zig");
|
||||
_ = @import("compiler_rt/addtf3.zig");
|
||||
_ = @import("compiler_rt/addxf3.zig");
|
||||
|
||||
_ = @import("compiler_rt/subsf3.zig");
|
||||
_ = @import("compiler_rt/subdf3.zig");
|
||||
_ = @import("compiler_rt/subtf3.zig");
|
||||
_ = @import("compiler_rt/subxf3.zig");
|
||||
|
||||
_ = @import("compiler_rt/mulf3.zig");
|
||||
_ = @import("compiler_rt/muldf3.zig");
|
||||
_ = @import("compiler_rt/mulsf3.zig");
|
||||
_ = @import("compiler_rt/multf3.zig");
|
||||
_ = @import("compiler_rt/mulxf3.zig");
|
||||
|
||||
_ = @import("compiler_rt/negsf2.zig");
|
||||
_ = @import("compiler_rt/negdf2.zig");
|
||||
_ = @import("compiler_rt/negtf2.zig");
|
||||
_ = @import("compiler_rt/negxf2.zig");
|
||||
|
||||
_ = @import("compiler_rt/comparef.zig");
|
||||
_ = @import("compiler_rt/cmpsf2.zig");
|
||||
_ = @import("compiler_rt/cmpdf2.zig");
|
||||
_ = @import("compiler_rt/cmptf2.zig");
|
||||
_ = @import("compiler_rt/cmpxf2.zig");
|
||||
_ = @import("compiler_rt/gesf2.zig");
|
||||
_ = @import("compiler_rt/gedf2.zig");
|
||||
_ = @import("compiler_rt/getf2.zig");
|
||||
_ = @import("compiler_rt/gexf2.zig");
|
||||
_ = @import("compiler_rt/unordsf2.zig");
|
||||
_ = @import("compiler_rt/unorddf2.zig");
|
||||
_ = @import("compiler_rt/unordtf2.zig");
|
||||
|
||||
_ = @import("compiler_rt/extendf.zig");
|
||||
_ = @import("compiler_rt/extenddftf2.zig");
|
||||
_ = @import("compiler_rt/extenddfxf2.zig");
|
||||
_ = @import("compiler_rt/extendhfsf2.zig");
|
||||
_ = @import("compiler_rt/extendhftf2.zig");
|
||||
_ = @import("compiler_rt/extendhfxf2.zig");
|
||||
_ = @import("compiler_rt/extendsfdf2.zig");
|
||||
_ = @import("compiler_rt/extendsftf2.zig");
|
||||
_ = @import("compiler_rt/extendsfxf2.zig");
|
||||
_ = @import("compiler_rt/extendxftf2.zig");
|
||||
|
||||
_ = @import("compiler_rt/truncf.zig");
|
||||
_ = @import("compiler_rt/truncsfhf2.zig");
|
||||
_ = @import("compiler_rt/truncdfhf2.zig");
|
||||
_ = @import("compiler_rt/truncdfsf2.zig");
|
||||
_ = @import("compiler_rt/trunctfhf2.zig");
|
||||
_ = @import("compiler_rt/trunctfsf2.zig");
|
||||
_ = @import("compiler_rt/trunctfdf2.zig");
|
||||
_ = @import("compiler_rt/trunctfxf2.zig");
|
||||
_ = @import("compiler_rt/truncxfhf2.zig");
|
||||
_ = @import("compiler_rt/truncxfsf2.zig");
|
||||
_ = @import("compiler_rt/truncxfdf2.zig");
|
||||
|
||||
_ = @import("compiler_rt/divtf3.zig");
|
||||
_ = @import("compiler_rt/divsf3.zig");
|
||||
_ = @import("compiler_rt/divdf3.zig");
|
||||
_ = @import("compiler_rt/divxf3.zig");
|
||||
_ = @import("compiler_rt/sin.zig");
|
||||
_ = @import("compiler_rt/cos.zig");
|
||||
_ = @import("compiler_rt/sincos.zig");
|
||||
_ = @import("compiler_rt/ceil.zig");
|
||||
_ = @import("compiler_rt/exp.zig");
|
||||
_ = @import("compiler_rt/exp2.zig");
|
||||
_ = @import("compiler_rt/fabs.zig");
|
||||
_ = @import("compiler_rt/floor.zig");
|
||||
_ = @import("compiler_rt/fma.zig");
|
||||
_ = @import("compiler_rt/fmax.zig");
|
||||
_ = @import("compiler_rt/fmin.zig");
|
||||
_ = @import("compiler_rt/fmod.zig");
|
||||
_ = @import("compiler_rt/log.zig");
|
||||
_ = @import("compiler_rt/log10.zig");
|
||||
_ = @import("compiler_rt/log2.zig");
|
||||
_ = @import("compiler_rt/round.zig");
|
||||
_ = @import("compiler_rt/sqrt.zig");
|
||||
_ = @import("compiler_rt/tan.zig");
|
||||
_ = @import("compiler_rt/trunc.zig");
|
||||
_ = @import("compiler_rt/stack_probe.zig");
|
||||
_ = @import("compiler_rt/divti3.zig");
|
||||
_ = @import("compiler_rt/modti3.zig");
|
||||
_ = @import("compiler_rt/multi3.zig");
|
||||
_ = @import("compiler_rt/udivti3.zig");
|
||||
_ = @import("compiler_rt/udivmodti4.zig");
|
||||
_ = @import("compiler_rt/umodti3.zig");
|
||||
|
||||
_ = @import("compiler_rt/int_to_float.zig");
|
||||
_ = @import("compiler_rt/floatsihf.zig");
|
||||
_ = @import("compiler_rt/floatsisf.zig");
|
||||
_ = @import("compiler_rt/floatsidf.zig");
|
||||
_ = @import("compiler_rt/floatsitf.zig");
|
||||
_ = @import("compiler_rt/floatsixf.zig");
|
||||
_ = @import("compiler_rt/floatdihf.zig");
|
||||
_ = @import("compiler_rt/floatdisf.zig");
|
||||
_ = @import("compiler_rt/floatdidf.zig");
|
||||
_ = @import("compiler_rt/floatditf.zig");
|
||||
_ = @import("compiler_rt/floatdixf.zig");
|
||||
_ = @import("compiler_rt/floattihf.zig");
|
||||
_ = @import("compiler_rt/floattisf.zig");
|
||||
_ = @import("compiler_rt/floattidf.zig");
|
||||
_ = @import("compiler_rt/floattitf.zig");
|
||||
_ = @import("compiler_rt/floattixf.zig");
|
||||
_ = @import("compiler_rt/floatundihf.zig");
|
||||
_ = @import("compiler_rt/floatundisf.zig");
|
||||
_ = @import("compiler_rt/floatundidf.zig");
|
||||
_ = @import("compiler_rt/floatunditf.zig");
|
||||
_ = @import("compiler_rt/floatundixf.zig");
|
||||
_ = @import("compiler_rt/floatunsihf.zig");
|
||||
_ = @import("compiler_rt/floatunsisf.zig");
|
||||
_ = @import("compiler_rt/floatunsidf.zig");
|
||||
_ = @import("compiler_rt/floatunsitf.zig");
|
||||
_ = @import("compiler_rt/floatunsixf.zig");
|
||||
_ = @import("compiler_rt/floatuntihf.zig");
|
||||
_ = @import("compiler_rt/floatuntisf.zig");
|
||||
_ = @import("compiler_rt/floatuntidf.zig");
|
||||
_ = @import("compiler_rt/floatuntitf.zig");
|
||||
_ = @import("compiler_rt/floatuntixf.zig");
|
||||
|
||||
_ = @import("compiler_rt/float_to_int.zig");
|
||||
_ = @import("compiler_rt/fixhfsi.zig");
|
||||
_ = @import("compiler_rt/fixhfdi.zig");
|
||||
_ = @import("compiler_rt/fixhfti.zig");
|
||||
_ = @import("compiler_rt/fixsfsi.zig");
|
||||
_ = @import("compiler_rt/fixsfdi.zig");
|
||||
_ = @import("compiler_rt/fixsfti.zig");
|
||||
_ = @import("compiler_rt/fixdfsi.zig");
|
||||
_ = @import("compiler_rt/fixdfdi.zig");
|
||||
_ = @import("compiler_rt/fixdfti.zig");
|
||||
_ = @import("compiler_rt/fixtfsi.zig");
|
||||
_ = @import("compiler_rt/fixtfdi.zig");
|
||||
_ = @import("compiler_rt/fixtfti.zig");
|
||||
_ = @import("compiler_rt/fixxfsi.zig");
|
||||
_ = @import("compiler_rt/fixxfdi.zig");
|
||||
_ = @import("compiler_rt/fixxfti.zig");
|
||||
_ = @import("compiler_rt/fixunshfsi.zig");
|
||||
_ = @import("compiler_rt/fixunshfdi.zig");
|
||||
_ = @import("compiler_rt/fixunshfti.zig");
|
||||
_ = @import("compiler_rt/fixunssfsi.zig");
|
||||
_ = @import("compiler_rt/fixunssfdi.zig");
|
||||
_ = @import("compiler_rt/fixunssfti.zig");
|
||||
_ = @import("compiler_rt/fixunsdfsi.zig");
|
||||
_ = @import("compiler_rt/fixunsdfdi.zig");
|
||||
_ = @import("compiler_rt/fixunsdfti.zig");
|
||||
_ = @import("compiler_rt/fixunstfsi.zig");
|
||||
_ = @import("compiler_rt/fixunstfdi.zig");
|
||||
_ = @import("compiler_rt/fixunstfti.zig");
|
||||
_ = @import("compiler_rt/fixunsxfsi.zig");
|
||||
_ = @import("compiler_rt/fixunsxfdi.zig");
|
||||
_ = @import("compiler_rt/fixunsxfti.zig");
|
||||
|
||||
_ = @import("compiler_rt/count0bits.zig");
|
||||
_ = @import("compiler_rt/parity.zig");
|
||||
_ = @import("compiler_rt/popcount.zig");
|
||||
_ = @import("compiler_rt/bswap.zig");
|
||||
_ = @import("compiler_rt/int.zig");
|
||||
_ = @import("compiler_rt/shift.zig");
|
||||
|
||||
_ = @import("compiler_rt/negXi2.zig");
|
||||
|
||||
_ = @import("compiler_rt/muldi3.zig");
|
||||
|
||||
_ = @import("compiler_rt/absv.zig");
|
||||
_ = @import("compiler_rt/absvsi2.zig");
|
||||
_ = @import("compiler_rt/absvdi2.zig");
|
||||
_ = @import("compiler_rt/absvti2.zig");
|
||||
|
||||
_ = @import("compiler_rt/negv.zig");
|
||||
_ = @import("compiler_rt/addo.zig");
|
||||
_ = @import("compiler_rt/subo.zig");
|
||||
_ = @import("compiler_rt/mulo.zig");
|
||||
_ = @import("compiler_rt/cmp.zig");
|
||||
|
||||
_ = @import("compiler_rt/os_version_check.zig");
|
||||
_ = @import("compiler_rt/emutls.zig");
|
||||
_ = @import("compiler_rt/arm.zig");
|
||||
_ = @import("compiler_rt/aulldiv.zig");
|
||||
_ = @import("compiler_rt/aullrem.zig");
|
||||
_ = @import("compiler_rt/clear_cache.zig");
|
||||
}
|
||||
267
lib/compiler_rt/README.md
Normal file
267
lib/compiler_rt/README.md
Normal file
@ -0,0 +1,267 @@
|
||||
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.
|
||||
|
||||
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 //
|
||||
- todo todo __fixxfsi //
|
||||
- todo todo __fixsfdi // convert a to i64, rounding towards zero
|
||||
- todo todo __fixdfdi //
|
||||
- todo todo __fixtfdi //
|
||||
- todo todo __fixxfdi //
|
||||
- todo todo __fixsfti // convert a to i128, rounding towards zero
|
||||
- todo todo __fixdfti //
|
||||
- todo todo __fixtfdi //
|
||||
- todo todo __fixxfti //
|
||||
|
||||
- __fixunssfsi // convert to u32, rounding towards zero. negative values become 0.
|
||||
- __fixunsdfsi //
|
||||
- __fixunstfsi //
|
||||
- __fixunsxfsi //
|
||||
- __fixunssfdi // convert to u64, rounding towards zero. negative values become 0.
|
||||
- __fixunsdfdi //
|
||||
- __fixunstfdi //
|
||||
- __fixunsxfdi //
|
||||
- __fixunssfti // convert to u128, rounding towards zero. negative values become 0.
|
||||
- __fixunsdfti //
|
||||
- __fixunstfdi //
|
||||
- __fixunsxfti //
|
||||
|
||||
- __floatsisf // convert i32 to floating point
|
||||
- __floatsidf //
|
||||
- __floatsitf //
|
||||
- __floatsixf //
|
||||
- __floatdisf // convert i64 to floating point
|
||||
- __floatdidf //
|
||||
- __floatditf //
|
||||
- __floatdixf //
|
||||
- __floattisf // convert i128 to floating point
|
||||
- __floattidf //
|
||||
- __floattixf //
|
||||
|
||||
- __floatunsisf // convert u32 to floating point
|
||||
- __floatunsidf //
|
||||
- __floatunsitf //
|
||||
- __floatunsixf //
|
||||
- __floatundisf // convert u64 to floating point
|
||||
- __floatundidf //
|
||||
- __floatunditf //
|
||||
- __floatundixf //
|
||||
- __floatuntisf // convert u128 to floating point
|
||||
- __floatuntidf //
|
||||
- __floatuntitf //
|
||||
- __floatuntixf //
|
||||
|
||||
#### 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
|
||||
- __divsf3 // a / b
|
||||
- __divdf3 // a / b
|
||||
- __divtf3 // a / b
|
||||
- __divxf3 // a / b
|
||||
- __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
|
||||
|
||||
#### 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 //
|
||||
@ -1,8 +1,6 @@
|
||||
// absv - absolute oVerflow
|
||||
// * @panic, if value can not be represented
|
||||
// - absvXi4_generic for unoptimized version
|
||||
|
||||
inline fn absvXi(comptime ST: type, a: ST) ST {
|
||||
/// absv - absolute oVerflow
|
||||
/// * @panic if value can not be represented
|
||||
pub inline fn absv(comptime ST: type, a: ST) ST {
|
||||
const UT = switch (ST) {
|
||||
i32 => u32,
|
||||
i64 => u64,
|
||||
@ -21,18 +19,6 @@ inline fn absvXi(comptime ST: type, a: ST) ST {
|
||||
return x;
|
||||
}
|
||||
|
||||
pub fn __absvsi2(a: i32) callconv(.C) i32 {
|
||||
return absvXi(i32, a);
|
||||
}
|
||||
|
||||
pub fn __absvdi2(a: i64) callconv(.C) i64 {
|
||||
return absvXi(i64, a);
|
||||
}
|
||||
|
||||
pub fn __absvti2(a: i128) callconv(.C) i128 {
|
||||
return absvXi(i128, a);
|
||||
}
|
||||
|
||||
test {
|
||||
_ = @import("absvsi2_test.zig");
|
||||
_ = @import("absvdi2_test.zig");
|
||||
12
lib/compiler_rt/absvdi2.zig
Normal file
12
lib/compiler_rt/absvdi2.zig
Normal file
@ -0,0 +1,12 @@
|
||||
const common = @import("./common.zig");
|
||||
const absv = @import("./absv.zig").absv;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__absvdi2, .{ .name = "__absvdi2", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
pub fn __absvdi2(a: i64) callconv(.C) i64 {
|
||||
return absv(i64, a);
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
const absv = @import("absv.zig");
|
||||
const testing = @import("std").testing;
|
||||
|
||||
const __absvdi2 = @import("absvdi2.zig").__absvdi2;
|
||||
|
||||
fn test__absvdi2(a: i64, expected: i64) !void {
|
||||
var result = absv.__absvdi2(a);
|
||||
var result = __absvdi2(a);
|
||||
try testing.expectEqual(expected, result);
|
||||
}
|
||||
|
||||
12
lib/compiler_rt/absvsi2.zig
Normal file
12
lib/compiler_rt/absvsi2.zig
Normal file
@ -0,0 +1,12 @@
|
||||
const common = @import("./common.zig");
|
||||
const absv = @import("./absv.zig").absv;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__absvsi2, .{ .name = "__absvsi2", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
pub fn __absvsi2(a: i32) callconv(.C) i32 {
|
||||
return absv(i32, a);
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
const absv = @import("absv.zig");
|
||||
const testing = @import("std").testing;
|
||||
|
||||
const __absvsi2 = @import("absvsi2.zig").__absvsi2;
|
||||
|
||||
fn test__absvsi2(a: i32, expected: i32) !void {
|
||||
var result = absv.__absvsi2(a);
|
||||
var result = __absvsi2(a);
|
||||
try testing.expectEqual(expected, result);
|
||||
}
|
||||
|
||||
12
lib/compiler_rt/absvti2.zig
Normal file
12
lib/compiler_rt/absvti2.zig
Normal file
@ -0,0 +1,12 @@
|
||||
const common = @import("./common.zig");
|
||||
const absv = @import("./absv.zig").absv;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__absvti2, .{ .name = "__absvti2", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
pub fn __absvti2(a: i128) callconv(.C) i128 {
|
||||
return absv(i128, a);
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
const absv = @import("absv.zig");
|
||||
const testing = @import("std").testing;
|
||||
|
||||
const __absvti2 = @import("absvti2.zig").__absvti2;
|
||||
|
||||
fn test__absvti2(a: i128, expected: i128) !void {
|
||||
var result = absv.__absvti2(a);
|
||||
var result = __absvti2(a);
|
||||
try testing.expectEqual(expected, result);
|
||||
}
|
||||
|
||||
20
lib/compiler_rt/adddf3.zig
Normal file
20
lib/compiler_rt/adddf3.zig
Normal file
@ -0,0 +1,20 @@
|
||||
const common = @import("./common.zig");
|
||||
const addf3 = @import("./addf3.zig").addf3;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (common.want_aeabi) {
|
||||
@export(__aeabi_dadd, .{ .name = "__aeabi_dadd", .linkage = common.linkage });
|
||||
} else {
|
||||
@export(__adddf3, .{ .name = "__adddf3", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
fn __adddf3(a: f64, b: f64) callconv(.C) f64 {
|
||||
return addf3(f64, a, b);
|
||||
}
|
||||
|
||||
fn __aeabi_dadd(a: f64, b: f64) callconv(.AAPCS) f64 {
|
||||
return addf3(f64, a, b);
|
||||
}
|
||||
@ -1,98 +1,37 @@
|
||||
// Ported from:
|
||||
//
|
||||
// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const compiler_rt = @import("../compiler_rt.zig");
|
||||
const math = std.math;
|
||||
const common = @import("./common.zig");
|
||||
const normalize = common.normalize;
|
||||
|
||||
pub fn __addsf3(a: f32, b: f32) callconv(.C) f32 {
|
||||
return addXf3(f32, a, b);
|
||||
}
|
||||
|
||||
pub fn __adddf3(a: f64, b: f64) callconv(.C) f64 {
|
||||
return addXf3(f64, a, b);
|
||||
}
|
||||
|
||||
pub fn __addtf3(a: f128, b: f128) callconv(.C) f128 {
|
||||
return addXf3(f128, a, b);
|
||||
}
|
||||
|
||||
pub fn __subsf3(a: f32, b: f32) callconv(.C) f32 {
|
||||
const neg_b = @bitCast(f32, @bitCast(u32, b) ^ (@as(u32, 1) << 31));
|
||||
return addXf3(f32, a, neg_b);
|
||||
}
|
||||
|
||||
pub fn __subdf3(a: f64, b: f64) callconv(.C) f64 {
|
||||
const neg_b = @bitCast(f64, @bitCast(u64, b) ^ (@as(u64, 1) << 63));
|
||||
return addXf3(f64, a, neg_b);
|
||||
}
|
||||
|
||||
pub fn __subtf3(a: f128, b: f128) callconv(.C) f128 {
|
||||
const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (@as(u128, 1) << 127));
|
||||
return addXf3(f128, a, neg_b);
|
||||
}
|
||||
|
||||
pub fn __aeabi_fadd(a: f32, b: f32) callconv(.AAPCS) f32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @call(.{ .modifier = .always_inline }, __addsf3, .{ a, b });
|
||||
}
|
||||
|
||||
pub fn __aeabi_dadd(a: f64, b: f64) callconv(.AAPCS) f64 {
|
||||
@setRuntimeSafety(false);
|
||||
return @call(.{ .modifier = .always_inline }, __adddf3, .{ a, b });
|
||||
}
|
||||
|
||||
pub fn __aeabi_fsub(a: f32, b: f32) callconv(.AAPCS) f32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @call(.{ .modifier = .always_inline }, __subsf3, .{ a, b });
|
||||
}
|
||||
|
||||
pub fn __aeabi_dsub(a: f64, b: f64) callconv(.AAPCS) f64 {
|
||||
@setRuntimeSafety(false);
|
||||
return @call(.{ .modifier = .always_inline }, __subdf3, .{ a, b });
|
||||
}
|
||||
|
||||
// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
|
||||
fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T).Float.bits)) i32 {
|
||||
const bits = @typeInfo(T).Float.bits;
|
||||
const Z = std.meta.Int(.unsigned, bits);
|
||||
const S = std.meta.Int(.unsigned, bits - @clz(Z, @as(Z, bits) - 1));
|
||||
const significandBits = std.math.floatMantissaBits(T);
|
||||
const implicitBit = @as(Z, 1) << significandBits;
|
||||
|
||||
const shift = @clz(std.meta.Int(.unsigned, bits), significand.*) - @clz(Z, implicitBit);
|
||||
significand.* <<= @intCast(S, shift);
|
||||
return 1 - shift;
|
||||
}
|
||||
|
||||
// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
|
||||
fn addXf3(comptime T: type, a: T, b: T) T {
|
||||
/// Ported from:
|
||||
///
|
||||
/// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc
|
||||
pub inline fn addf3(comptime T: type, a: T, b: T) T {
|
||||
const bits = @typeInfo(T).Float.bits;
|
||||
const Z = std.meta.Int(.unsigned, bits);
|
||||
const S = std.meta.Int(.unsigned, bits - @clz(Z, @as(Z, bits) - 1));
|
||||
|
||||
const typeWidth = bits;
|
||||
const significandBits = std.math.floatMantissaBits(T);
|
||||
const exponentBits = std.math.floatExponentBits(T);
|
||||
const significandBits = math.floatMantissaBits(T);
|
||||
const fractionalBits = math.floatFractionalBits(T);
|
||||
const exponentBits = math.floatExponentBits(T);
|
||||
|
||||
const signBit = (@as(Z, 1) << (significandBits + exponentBits));
|
||||
const maxExponent = ((1 << exponentBits) - 1);
|
||||
|
||||
const implicitBit = (@as(Z, 1) << significandBits);
|
||||
const quietBit = implicitBit >> 1;
|
||||
const significandMask = implicitBit - 1;
|
||||
const integerBit = (@as(Z, 1) << fractionalBits);
|
||||
const quietBit = integerBit >> 1;
|
||||
const significandMask = (@as(Z, 1) << significandBits) - 1;
|
||||
|
||||
const absMask = signBit - 1;
|
||||
const exponentMask = absMask ^ significandMask;
|
||||
const qnanRep = exponentMask | quietBit;
|
||||
const qnanRep = @bitCast(Z, math.nan(T)) | quietBit;
|
||||
|
||||
var aRep = @bitCast(Z, a);
|
||||
var bRep = @bitCast(Z, b);
|
||||
const aAbs = aRep & absMask;
|
||||
const bAbs = bRep & absMask;
|
||||
|
||||
const infRep = @bitCast(Z, std.math.inf(T));
|
||||
const infRep = @bitCast(Z, math.inf(T));
|
||||
|
||||
// Detect if a or b is zero, infinity, or NaN.
|
||||
if (aAbs -% @as(Z, 1) >= infRep - @as(Z, 1) or
|
||||
@ -157,12 +96,12 @@ fn addXf3(comptime T: type, a: T, b: T) T {
|
||||
// implicit significand bit. (If we fell through from the denormal path it
|
||||
// was already set by normalize( ), but setting it twice won't hurt
|
||||
// anything.)
|
||||
aSignificand = (aSignificand | implicitBit) << 3;
|
||||
bSignificand = (bSignificand | implicitBit) << 3;
|
||||
aSignificand = (aSignificand | integerBit) << 3;
|
||||
bSignificand = (bSignificand | integerBit) << 3;
|
||||
|
||||
// Shift the significand of b by the difference in exponents, with a sticky
|
||||
// bottom bit to get rounding correct.
|
||||
const @"align" = @intCast(Z, aExponent - bExponent);
|
||||
const @"align" = @intCast(u32, aExponent - bExponent);
|
||||
if (@"align" != 0) {
|
||||
if (@"align" < typeWidth) {
|
||||
const sticky = if (bSignificand << @intCast(S, typeWidth - @"align") != 0) @as(Z, 1) else 0;
|
||||
@ -178,8 +117,8 @@ fn addXf3(comptime T: type, a: T, b: T) T {
|
||||
|
||||
// If partial cancellation occured, we need to left-shift the result
|
||||
// and adjust the exponent:
|
||||
if (aSignificand < implicitBit << 3) {
|
||||
const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(std.meta.Int(.unsigned, bits), implicitBit << 3));
|
||||
if (aSignificand < integerBit << 3) {
|
||||
const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(std.meta.Int(.unsigned, bits), integerBit << 3));
|
||||
aSignificand <<= @intCast(S, shift);
|
||||
aExponent -= shift;
|
||||
}
|
||||
@ -188,7 +127,7 @@ fn addXf3(comptime T: type, a: T, b: T) T {
|
||||
|
||||
// If the addition carried up, we need to right-shift the result and
|
||||
// adjust the exponent:
|
||||
if (aSignificand & (implicitBit << 4) != 0) {
|
||||
if (aSignificand & (integerBit << 4) != 0) {
|
||||
const sticky = aSignificand & 1;
|
||||
aSignificand = aSignificand >> 1 | sticky;
|
||||
aExponent += 1;
|
||||
@ -199,18 +138,16 @@ fn addXf3(comptime T: type, a: T, b: T) T {
|
||||
if (aExponent >= maxExponent) return @bitCast(T, infRep | resultSign);
|
||||
|
||||
if (aExponent <= 0) {
|
||||
// Result is denormal before rounding; the exponent is zero and we
|
||||
// need to shift the significand.
|
||||
const shift = @intCast(Z, 1 - aExponent);
|
||||
const sticky = if (aSignificand << @intCast(S, typeWidth - shift) != 0) @as(Z, 1) else 0;
|
||||
aSignificand = aSignificand >> @intCast(S, shift | sticky);
|
||||
aExponent = 0;
|
||||
// Result is denormal; the exponent and round/sticky bits are zero.
|
||||
// All we need to do is shift the significand and apply the correct sign.
|
||||
aSignificand >>= @intCast(S, 4 - aExponent);
|
||||
return @bitCast(T, resultSign | aSignificand);
|
||||
}
|
||||
|
||||
// Low three bits are round, guard, and sticky.
|
||||
const roundGuardSticky = aSignificand & 0x7;
|
||||
|
||||
// Shift the significand into place, and mask off the implicit bit.
|
||||
// Shift the significand into place, and mask off the integer bit, if it's implicit.
|
||||
var result = (aSignificand >> 3) & significandMask;
|
||||
|
||||
// Insert the exponent and sign.
|
||||
@ -222,9 +159,14 @@ fn addXf3(comptime T: type, a: T, b: T) T {
|
||||
if (roundGuardSticky > 0x4) result += 1;
|
||||
if (roundGuardSticky == 0x4) result += result & 1;
|
||||
|
||||
// Restore any explicit integer bit, if it was rounded off
|
||||
if (significandBits != fractionalBits) {
|
||||
if ((result >> significandBits) != 0) result |= integerBit;
|
||||
}
|
||||
|
||||
return @bitCast(T, result);
|
||||
}
|
||||
|
||||
test {
|
||||
_ = @import("addXf3_test.zig");
|
||||
_ = @import("addf3_test.zig");
|
||||
}
|
||||
156
lib/compiler_rt/addf3_test.zig
Normal file
156
lib/compiler_rt/addf3_test.zig
Normal file
@ -0,0 +1,156 @@
|
||||
// Ported from:
|
||||
//
|
||||
// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/addtf3_test.c
|
||||
// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/subtf3_test.c
|
||||
|
||||
const std = @import("std");
|
||||
const math = std.math;
|
||||
const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64);
|
||||
|
||||
const __addtf3 = @import("addtf3.zig").__addtf3;
|
||||
const __addxf3 = @import("addxf3.zig").__addxf3;
|
||||
const __subtf3 = @import("subtf3.zig").__subtf3;
|
||||
|
||||
fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
|
||||
const x = __addtf3(a, b);
|
||||
|
||||
const rep = @bitCast(u128, x);
|
||||
const hi = @intCast(u64, rep >> 64);
|
||||
const lo = @truncate(u64, rep);
|
||||
|
||||
if (hi == expected_hi and lo == expected_lo) {
|
||||
return;
|
||||
}
|
||||
// test other possible NaN representation (signal NaN)
|
||||
else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
|
||||
if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
|
||||
((hi & 0xffffffffffff) > 0 or lo > 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return error.TestFailed;
|
||||
}
|
||||
|
||||
test "addtf3" {
|
||||
try test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
||||
|
||||
// NaN + any = NaN
|
||||
try test__addtf3(@bitCast(f128, (@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
||||
|
||||
// inf + inf = inf
|
||||
try test__addtf3(math.inf(f128), math.inf(f128), 0x7fff000000000000, 0x0);
|
||||
|
||||
// inf + any = inf
|
||||
try test__addtf3(math.inf(f128), 0x1.2335653452436234723489432abcdefp+5, 0x7fff000000000000, 0x0);
|
||||
|
||||
// any + any
|
||||
try test__addtf3(0x1.23456734245345543849abcdefp+5, 0x1.edcba52449872455634654321fp-1, 0x40042afc95c8b579, 0x61e58dd6c51eb77c);
|
||||
try test__addtf3(0x1.edcba52449872455634654321fp-1, 0x1.23456734245345543849abcdefp+5, 0x40042afc95c8b579, 0x61e58dd6c51eb77c);
|
||||
}
|
||||
|
||||
fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void {
|
||||
const x = __subtf3(a, b);
|
||||
|
||||
const rep = @bitCast(u128, x);
|
||||
const hi = @intCast(u64, rep >> 64);
|
||||
const lo = @truncate(u64, rep);
|
||||
|
||||
if (hi == expected_hi and lo == expected_lo) {
|
||||
return;
|
||||
}
|
||||
// test other possible NaN representation (signal NaN)
|
||||
else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
|
||||
if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
|
||||
((hi & 0xffffffffffff) > 0 or lo > 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return error.TestFailed;
|
||||
}
|
||||
|
||||
test "subtf3" {
|
||||
// qNaN - any = qNaN
|
||||
try test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
||||
|
||||
// NaN + any = NaN
|
||||
try test__subtf3(@bitCast(f128, (@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
|
||||
|
||||
// inf - any = inf
|
||||
try test__subtf3(math.inf(f128), 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0);
|
||||
|
||||
// any + any
|
||||
try test__subtf3(0x1.234567829a3bcdef5678ade36734p+5, 0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x40041b8af1915166, 0xa44a7bca780a166c);
|
||||
try test__subtf3(0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x1.234567829a3bcdef5678ade36734p+5, 0xc0041b8af1915166, 0xa44a7bca780a166c);
|
||||
}
|
||||
|
||||
const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1)));
|
||||
|
||||
fn test__addxf3(a: f80, b: f80, expected: u80) !void {
|
||||
const x = __addxf3(a, b);
|
||||
const rep = @bitCast(u80, x);
|
||||
|
||||
if (rep == expected)
|
||||
return;
|
||||
|
||||
if (math.isNan(@bitCast(f80, expected)) and math.isNan(x))
|
||||
return; // We don't currently test NaN payload propagation
|
||||
|
||||
return error.TestFailed;
|
||||
}
|
||||
|
||||
test "addxf3" {
|
||||
// NaN + any = NaN
|
||||
try test__addxf3(qnan80, 0x1.23456789abcdefp+5, @bitCast(u80, qnan80));
|
||||
try test__addxf3(@bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), 0x1.23456789abcdefp+5, @bitCast(u80, qnan80));
|
||||
|
||||
// any + NaN = NaN
|
||||
try test__addxf3(0x1.23456789abcdefp+5, qnan80, @bitCast(u80, qnan80));
|
||||
try test__addxf3(0x1.23456789abcdefp+5, @bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), @bitCast(u80, qnan80));
|
||||
|
||||
// NaN + inf = NaN
|
||||
try test__addxf3(qnan80, math.inf(f80), @bitCast(u80, qnan80));
|
||||
|
||||
// inf + NaN = NaN
|
||||
try test__addxf3(math.inf(f80), qnan80, @bitCast(u80, qnan80));
|
||||
|
||||
// inf + inf = inf
|
||||
try test__addxf3(math.inf(f80), math.inf(f80), @bitCast(u80, math.inf(f80)));
|
||||
|
||||
// inf + -inf = NaN
|
||||
try test__addxf3(math.inf(f80), -math.inf(f80), @bitCast(u80, qnan80));
|
||||
|
||||
// -inf + inf = NaN
|
||||
try test__addxf3(-math.inf(f80), math.inf(f80), @bitCast(u80, qnan80));
|
||||
|
||||
// inf + any = inf
|
||||
try test__addxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @bitCast(u80, math.inf(f80)));
|
||||
|
||||
// any + inf = inf
|
||||
try test__addxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @bitCast(u80, math.inf(f80)));
|
||||
|
||||
// any + any
|
||||
try test__addxf3(0x1.23456789abcdp+5, 0x1.dcba987654321p+5, 0x4005_BFFFFFFFFFFFC400);
|
||||
try test__addxf3(0x1.23456734245345543849abcdefp+5, 0x1.edcba52449872455634654321fp-1, 0x4004_957E_4AE4_5ABC_B0F3);
|
||||
try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.0p-63, 0x3FFF_FFFFFFFFFFFFFFFF); // exact
|
||||
try test__addxf3(0x1.ffff_ffff_ffff_fffep+0, 0x0.0p0, 0x3FFF_FFFFFFFFFFFFFFFF); // exact
|
||||
try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.4p-63, 0x3FFF_FFFFFFFFFFFFFFFF); // round down
|
||||
try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.8p-63, 0x4000_8000000000000000); // round up to even
|
||||
try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.cp-63, 0x4000_8000000000000000); // round up
|
||||
try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x2.0p-63, 0x4000_8000000000000000); // exact
|
||||
try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x2.1p-63, 0x4000_8000000000000000); // round down
|
||||
try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x3.0p-63, 0x4000_8000000000000000); // round down to even
|
||||
try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x3.1p-63, 0x4000_8000000000000001); // round up
|
||||
try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x4.0p-63, 0x4000_8000000000000001); // exact
|
||||
|
||||
try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.0p-63, 0x3FFF_8800000000000000); // exact
|
||||
try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.7p-63, 0x3FFF_8800000000000000); // round down
|
||||
try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.8p-63, 0x3FFF_8800000000000000); // round down to even
|
||||
try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.9p-63, 0x3FFF_8800000000000001); // round up
|
||||
try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x2.0p-63, 0x3FFF_8800000000000001); // exact
|
||||
try test__addxf3(0x0.ffff_ffff_ffff_fffcp-16382, 0x0.0000_0000_0000_0002p-16382, 0x0000_7FFFFFFFFFFFFFFF); // exact
|
||||
try test__addxf3(0x0.1fff_ffff_ffff_fffcp-16382, 0x0.0000_0000_0000_0002p-16382, 0x0000_0FFFFFFFFFFFFFFF); // exact
|
||||
}
|
||||
48
lib/compiler_rt/addo.zig
Normal file
48
lib/compiler_rt/addo.zig
Normal file
@ -0,0 +1,48 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
|
||||
pub const panic = @import("common.zig").panic;
|
||||
|
||||
comptime {
|
||||
@export(__addosi4, .{ .name = "__addosi4", .linkage = linkage });
|
||||
@export(__addodi4, .{ .name = "__addodi4", .linkage = linkage });
|
||||
@export(__addoti4, .{ .name = "__addoti4", .linkage = linkage });
|
||||
}
|
||||
|
||||
// addo - add overflow
|
||||
// * return a+%b.
|
||||
// * return if a+b overflows => 1 else => 0
|
||||
// - addoXi4_generic as default
|
||||
|
||||
inline fn addoXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
overflow.* = 0;
|
||||
var sum: ST = a +% b;
|
||||
// Hackers Delight: section Overflow Detection, subsection Signed Add/Subtract
|
||||
// Let sum = a +% b == a + b + carry == wraparound addition.
|
||||
// Overflow in a+b+carry occurs, iff a and b have opposite signs
|
||||
// and the sign of a+b+carry is the same as a (or equivalently b).
|
||||
// Slower routine: res = ~(a ^ b) & ((sum ^ a)
|
||||
// Faster routine: res = (sum ^ a) & (sum ^ b)
|
||||
// Overflow occured, iff (res < 0)
|
||||
if (((sum ^ a) & (sum ^ b)) < 0)
|
||||
overflow.* = 1;
|
||||
return sum;
|
||||
}
|
||||
|
||||
pub fn __addosi4(a: i32, b: i32, overflow: *c_int) callconv(.C) i32 {
|
||||
return addoXi4_generic(i32, a, b, overflow);
|
||||
}
|
||||
pub fn __addodi4(a: i64, b: i64, overflow: *c_int) callconv(.C) i64 {
|
||||
return addoXi4_generic(i64, a, b, overflow);
|
||||
}
|
||||
pub fn __addoti4(a: i128, b: i128, overflow: *c_int) callconv(.C) i128 {
|
||||
return addoXi4_generic(i128, a, b, overflow);
|
||||
}
|
||||
|
||||
test {
|
||||
_ = @import("addosi4_test.zig");
|
||||
_ = @import("addodi4_test.zig");
|
||||
_ = @import("addoti4_test.zig");
|
||||
}
|
||||
77
lib/compiler_rt/addodi4_test.zig
Normal file
77
lib/compiler_rt/addodi4_test.zig
Normal file
@ -0,0 +1,77 @@
|
||||
const addv = @import("addo.zig");
|
||||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
const math = std.math;
|
||||
|
||||
fn test__addodi4(a: i64, b: i64) !void {
|
||||
var result_ov: c_int = undefined;
|
||||
var expected_ov: c_int = undefined;
|
||||
var result = addv.__addodi4(a, b, &result_ov);
|
||||
var expected: i64 = simple_addodi4(a, b, &expected_ov);
|
||||
try testing.expectEqual(expected, result);
|
||||
try testing.expectEqual(expected_ov, result_ov);
|
||||
}
|
||||
|
||||
fn simple_addodi4(a: i64, b: i64, overflow: *c_int) i64 {
|
||||
overflow.* = 0;
|
||||
const min: i64 = math.minInt(i64);
|
||||
const max: i64 = math.maxInt(i64);
|
||||
if (((a > 0) and (b > max - a)) or
|
||||
((a < 0) and (b < min - a)))
|
||||
overflow.* = 1;
|
||||
return a +% b;
|
||||
}
|
||||
|
||||
test "addodi4" {
|
||||
const min: i64 = math.minInt(i64);
|
||||
const max: i64 = math.maxInt(i64);
|
||||
var i: i64 = 1;
|
||||
while (i < max) : (i *|= 2) {
|
||||
try test__addodi4(i, i);
|
||||
try test__addodi4(-i, -i);
|
||||
try test__addodi4(i, -i);
|
||||
try test__addodi4(-i, i);
|
||||
}
|
||||
|
||||
// edge cases
|
||||
// 0 + 0 = 0
|
||||
// MIN + MIN overflow
|
||||
// MAX + MAX overflow
|
||||
// 0 + MIN MIN
|
||||
// 0 + MAX MAX
|
||||
// MIN + 0 MIN
|
||||
// MAX + 0 MAX
|
||||
// MIN + MAX -1
|
||||
// MAX + MIN -1
|
||||
try test__addodi4(0, 0);
|
||||
try test__addodi4(min, min);
|
||||
try test__addodi4(max, max);
|
||||
try test__addodi4(0, min);
|
||||
try test__addodi4(0, max);
|
||||
try test__addodi4(min, 0);
|
||||
try test__addodi4(max, 0);
|
||||
try test__addodi4(min, max);
|
||||
try test__addodi4(max, min);
|
||||
|
||||
// derived edge cases
|
||||
// MIN+1 + MIN overflow
|
||||
// MAX-1 + MAX overflow
|
||||
// 1 + MIN = MIN+1
|
||||
// -1 + MIN overflow
|
||||
// -1 + MAX = MAX-1
|
||||
// +1 + MAX overflow
|
||||
// MIN + 1 = MIN+1
|
||||
// MIN + -1 overflow
|
||||
// MAX + 1 overflow
|
||||
// MAX + -1 = MAX-1
|
||||
try test__addodi4(min + 1, min);
|
||||
try test__addodi4(max - 1, max);
|
||||
try test__addodi4(1, min);
|
||||
try test__addodi4(-1, min);
|
||||
try test__addodi4(-1, max);
|
||||
try test__addodi4(1, max);
|
||||
try test__addodi4(min, 1);
|
||||
try test__addodi4(min, -1);
|
||||
try test__addodi4(max, -1);
|
||||
try test__addodi4(max, 1);
|
||||
}
|
||||
78
lib/compiler_rt/addosi4_test.zig
Normal file
78
lib/compiler_rt/addosi4_test.zig
Normal file
@ -0,0 +1,78 @@
|
||||
const addv = @import("addo.zig");
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__addosi4(a: i32, b: i32) !void {
|
||||
var result_ov: c_int = undefined;
|
||||
var expected_ov: c_int = undefined;
|
||||
var result = addv.__addosi4(a, b, &result_ov);
|
||||
var expected: i32 = simple_addosi4(a, b, &expected_ov);
|
||||
try testing.expectEqual(expected, result);
|
||||
try testing.expectEqual(expected_ov, result_ov);
|
||||
}
|
||||
|
||||
fn simple_addosi4(a: i32, b: i32, overflow: *c_int) i32 {
|
||||
overflow.* = 0;
|
||||
const min: i32 = -2147483648;
|
||||
const max: i32 = 2147483647;
|
||||
if (((a > 0) and (b > max - a)) or
|
||||
((a < 0) and (b < min - a)))
|
||||
overflow.* = 1;
|
||||
return a +% b;
|
||||
}
|
||||
|
||||
test "addosi4" {
|
||||
// -2^31 <= i32 <= 2^31-1
|
||||
// 2^31 = 2147483648
|
||||
// 2^31-1 = 2147483647
|
||||
const min: i32 = -2147483648;
|
||||
const max: i32 = 2147483647;
|
||||
var i: i32 = 1;
|
||||
while (i < max) : (i *|= 2) {
|
||||
try test__addosi4(i, i);
|
||||
try test__addosi4(-i, -i);
|
||||
try test__addosi4(i, -i);
|
||||
try test__addosi4(-i, i);
|
||||
}
|
||||
|
||||
// edge cases
|
||||
// 0 + 0 = 0
|
||||
// MIN + MIN overflow
|
||||
// MAX + MAX overflow
|
||||
// 0 + MIN MIN
|
||||
// 0 + MAX MAX
|
||||
// MIN + 0 MIN
|
||||
// MAX + 0 MAX
|
||||
// MIN + MAX -1
|
||||
// MAX + MIN -1
|
||||
try test__addosi4(0, 0);
|
||||
try test__addosi4(min, min);
|
||||
try test__addosi4(max, max);
|
||||
try test__addosi4(0, min);
|
||||
try test__addosi4(0, max);
|
||||
try test__addosi4(min, 0);
|
||||
try test__addosi4(max, 0);
|
||||
try test__addosi4(min, max);
|
||||
try test__addosi4(max, min);
|
||||
|
||||
// derived edge cases
|
||||
// MIN+1 + MIN overflow
|
||||
// MAX-1 + MAX overflow
|
||||
// 1 + MIN = MIN+1
|
||||
// -1 + MIN overflow
|
||||
// -1 + MAX = MAX-1
|
||||
// +1 + MAX overflow
|
||||
// MIN + 1 = MIN+1
|
||||
// MIN + -1 overflow
|
||||
// MAX + 1 overflow
|
||||
// MAX + -1 = MAX-1
|
||||
try test__addosi4(min + 1, min);
|
||||
try test__addosi4(max - 1, max);
|
||||
try test__addosi4(1, min);
|
||||
try test__addosi4(-1, min);
|
||||
try test__addosi4(-1, max);
|
||||
try test__addosi4(1, max);
|
||||
try test__addosi4(min, 1);
|
||||
try test__addosi4(min, -1);
|
||||
try test__addosi4(max, -1);
|
||||
try test__addosi4(max, 1);
|
||||
}
|
||||
77
lib/compiler_rt/addoti4_test.zig
Normal file
77
lib/compiler_rt/addoti4_test.zig
Normal file
@ -0,0 +1,77 @@
|
||||
const addv = @import("addo.zig");
|
||||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
const math = std.math;
|
||||
|
||||
fn test__addoti4(a: i128, b: i128) !void {
|
||||
var result_ov: c_int = undefined;
|
||||
var expected_ov: c_int = undefined;
|
||||
var result = addv.__addoti4(a, b, &result_ov);
|
||||
var expected: i128 = simple_addoti4(a, b, &expected_ov);
|
||||
try testing.expectEqual(expected, result);
|
||||
try testing.expectEqual(expected_ov, result_ov);
|
||||
}
|
||||
|
||||
fn simple_addoti4(a: i128, b: i128, overflow: *c_int) i128 {
|
||||
overflow.* = 0;
|
||||
const min: i128 = math.minInt(i128);
|
||||
const max: i128 = math.maxInt(i128);
|
||||
if (((a > 0) and (b > max - a)) or
|
||||
((a < 0) and (b < min - a)))
|
||||
overflow.* = 1;
|
||||
return a +% b;
|
||||
}
|
||||
|
||||
test "addoti4" {
|
||||
const min: i128 = math.minInt(i128);
|
||||
const max: i128 = math.maxInt(i128);
|
||||
var i: i128 = 1;
|
||||
while (i < max) : (i *|= 2) {
|
||||
try test__addoti4(i, i);
|
||||
try test__addoti4(-i, -i);
|
||||
try test__addoti4(i, -i);
|
||||
try test__addoti4(-i, i);
|
||||
}
|
||||
|
||||
// edge cases
|
||||
// 0 + 0 = 0
|
||||
// MIN + MIN overflow
|
||||
// MAX + MAX overflow
|
||||
// 0 + MIN MIN
|
||||
// 0 + MAX MAX
|
||||
// MIN + 0 MIN
|
||||
// MAX + 0 MAX
|
||||
// MIN + MAX -1
|
||||
// MAX + MIN -1
|
||||
try test__addoti4(0, 0);
|
||||
try test__addoti4(min, min);
|
||||
try test__addoti4(max, max);
|
||||
try test__addoti4(0, min);
|
||||
try test__addoti4(0, max);
|
||||
try test__addoti4(min, 0);
|
||||
try test__addoti4(max, 0);
|
||||
try test__addoti4(min, max);
|
||||
try test__addoti4(max, min);
|
||||
|
||||
// derived edge cases
|
||||
// MIN+1 + MIN overflow
|
||||
// MAX-1 + MAX overflow
|
||||
// 1 + MIN = MIN+1
|
||||
// -1 + MIN overflow
|
||||
// -1 + MAX = MAX-1
|
||||
// +1 + MAX overflow
|
||||
// MIN + 1 = MIN+1
|
||||
// MIN + -1 overflow
|
||||
// MAX + 1 overflow
|
||||
// MAX + -1 = MAX-1
|
||||
try test__addoti4(min + 1, min);
|
||||
try test__addoti4(max - 1, max);
|
||||
try test__addoti4(1, min);
|
||||
try test__addoti4(-1, min);
|
||||
try test__addoti4(-1, max);
|
||||
try test__addoti4(1, max);
|
||||
try test__addoti4(min, 1);
|
||||
try test__addoti4(min, -1);
|
||||
try test__addoti4(max, -1);
|
||||
try test__addoti4(max, 1);
|
||||
}
|
||||
20
lib/compiler_rt/addsf3.zig
Normal file
20
lib/compiler_rt/addsf3.zig
Normal file
@ -0,0 +1,20 @@
|
||||
const common = @import("./common.zig");
|
||||
const addf3 = @import("./addf3.zig").addf3;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (common.want_aeabi) {
|
||||
@export(__aeabi_fadd, .{ .name = "__aeabi_fadd", .linkage = common.linkage });
|
||||
} else {
|
||||
@export(__addsf3, .{ .name = "__addsf3", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
fn __addsf3(a: f32, b: f32) callconv(.C) f32 {
|
||||
return addf3(f32, a, b);
|
||||
}
|
||||
|
||||
fn __aeabi_fadd(a: f32, b: f32) callconv(.AAPCS) f32 {
|
||||
return addf3(f32, a, b);
|
||||
}
|
||||
26
lib/compiler_rt/addtf3.zig
Normal file
26
lib/compiler_rt/addtf3.zig
Normal file
@ -0,0 +1,26 @@
|
||||
const common = @import("./common.zig");
|
||||
const addf3 = @import("./addf3.zig").addf3;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (common.want_ppc_abi) {
|
||||
@export(__addkf3, .{ .name = "__addkf3", .linkage = common.linkage });
|
||||
} else if (common.want_sparc_abi) {
|
||||
@export(_Qp_add, .{ .name = "_Qp_add", .linkage = common.linkage });
|
||||
} else {
|
||||
@export(__addtf3, .{ .name = "__addtf3", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __addtf3(a: f128, b: f128) callconv(.C) f128 {
|
||||
return addf3(f128, a, b);
|
||||
}
|
||||
|
||||
fn __addkf3(a: f128, b: f128) callconv(.C) f128 {
|
||||
return addf3(f128, a, b);
|
||||
}
|
||||
|
||||
fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.C) void {
|
||||
c.* = addf3(f128, a.*, b.*);
|
||||
}
|
||||
12
lib/compiler_rt/addxf3.zig
Normal file
12
lib/compiler_rt/addxf3.zig
Normal file
@ -0,0 +1,12 @@
|
||||
const common = @import("./common.zig");
|
||||
const addf3 = @import("./addf3.zig").addf3;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__addxf3, .{ .name = "__addxf3", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 {
|
||||
return addf3(f80, a, b);
|
||||
}
|
||||
188
lib/compiler_rt/arm.zig
Normal file
188
lib/compiler_rt/arm.zig
Normal file
@ -0,0 +1,188 @@
|
||||
// ARM specific builtins
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
const common = @import("common.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (!builtin.is_test) {
|
||||
if (arch.isARM() or arch.isThumb()) {
|
||||
@export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = common.linkage });
|
||||
@export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = common.linkage });
|
||||
@export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = common.linkage });
|
||||
|
||||
@export(__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = common.linkage });
|
||||
@export(__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = common.linkage });
|
||||
|
||||
@export(__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = common.linkage });
|
||||
@export(__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = common.linkage });
|
||||
|
||||
@export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = common.linkage });
|
||||
@export(__aeabi_memcpy4, .{ .name = "__aeabi_memcpy4", .linkage = common.linkage });
|
||||
@export(__aeabi_memcpy8, .{ .name = "__aeabi_memcpy8", .linkage = common.linkage });
|
||||
|
||||
@export(__aeabi_memmove, .{ .name = "__aeabi_memmove", .linkage = common.linkage });
|
||||
@export(__aeabi_memmove4, .{ .name = "__aeabi_memmove4", .linkage = common.linkage });
|
||||
@export(__aeabi_memmove8, .{ .name = "__aeabi_memmove8", .linkage = common.linkage });
|
||||
|
||||
@export(__aeabi_memset, .{ .name = "__aeabi_memset", .linkage = common.linkage });
|
||||
@export(__aeabi_memset4, .{ .name = "__aeabi_memset4", .linkage = common.linkage });
|
||||
@export(__aeabi_memset8, .{ .name = "__aeabi_memset8", .linkage = common.linkage });
|
||||
|
||||
@export(__aeabi_memclr, .{ .name = "__aeabi_memclr", .linkage = common.linkage });
|
||||
@export(__aeabi_memclr4, .{ .name = "__aeabi_memclr4", .linkage = common.linkage });
|
||||
@export(__aeabi_memclr8, .{ .name = "__aeabi_memclr8", .linkage = common.linkage });
|
||||
|
||||
if (builtin.os.tag == .linux) {
|
||||
@export(__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const __divmodsi4 = @import("int.zig").__divmodsi4;
|
||||
const __udivmodsi4 = @import("int.zig").__udivmodsi4;
|
||||
const __divmoddi4 = @import("int.zig").__divmoddi4;
|
||||
const __udivmoddi4 = @import("int.zig").__udivmoddi4;
|
||||
|
||||
extern fn memset(dest: ?[*]u8, c: u8, n: usize) ?[*]u8;
|
||||
extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) ?[*]u8;
|
||||
extern fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) ?[*]u8;
|
||||
|
||||
pub fn __aeabi_memcpy(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
_ = memcpy(dest, src, n);
|
||||
}
|
||||
pub fn __aeabi_memcpy4(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
_ = memcpy(dest, src, n);
|
||||
}
|
||||
pub fn __aeabi_memcpy8(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
_ = memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
pub fn __aeabi_memmove(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
_ = memmove(dest, src, n);
|
||||
}
|
||||
pub fn __aeabi_memmove4(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
_ = memmove(dest, src, n);
|
||||
}
|
||||
pub fn __aeabi_memmove8(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
_ = memmove(dest, src, n);
|
||||
}
|
||||
|
||||
pub fn __aeabi_memset(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
// This is dentical to the standard `memset` definition but with the last
|
||||
// two arguments swapped
|
||||
_ = memset(dest, c, n);
|
||||
}
|
||||
pub fn __aeabi_memset4(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
_ = memset(dest, c, n);
|
||||
}
|
||||
pub fn __aeabi_memset8(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
_ = memset(dest, c, n);
|
||||
}
|
||||
|
||||
pub fn __aeabi_memclr(dest: [*]u8, n: usize) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
_ = memset(dest, 0, n);
|
||||
}
|
||||
pub fn __aeabi_memclr4(dest: [*]u8, n: usize) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
_ = memset(dest, 0, n);
|
||||
}
|
||||
pub fn __aeabi_memclr8(dest: [*]u8, n: usize) callconv(.AAPCS) void {
|
||||
@setRuntimeSafety(false);
|
||||
_ = memset(dest, 0, n);
|
||||
}
|
||||
|
||||
// Dummy functions to avoid errors during the linking phase
|
||||
pub fn __aeabi_unwind_cpp_pr0() callconv(.AAPCS) void {}
|
||||
pub fn __aeabi_unwind_cpp_pr1() callconv(.AAPCS) void {}
|
||||
pub fn __aeabi_unwind_cpp_pr2() callconv(.AAPCS) void {}
|
||||
|
||||
// This function can only clobber r0 according to the ABI
|
||||
pub fn __aeabi_read_tp() callconv(.Naked) void {
|
||||
@setRuntimeSafety(false);
|
||||
asm volatile (
|
||||
\\ mrc p15, 0, r0, c13, c0, 3
|
||||
\\ bx lr
|
||||
);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
// The following functions are wrapped in an asm block to ensure the required
|
||||
// calling convention is always respected
|
||||
|
||||
pub fn __aeabi_uidivmod() callconv(.Naked) void {
|
||||
@setRuntimeSafety(false);
|
||||
// Divide r0 by r1; the quotient goes in r0, the remainder in r1
|
||||
asm volatile (
|
||||
\\ push {lr}
|
||||
\\ sub sp, #4
|
||||
\\ mov r2, sp
|
||||
\\ bl __udivmodsi4
|
||||
\\ ldr r1, [sp]
|
||||
\\ add sp, #4
|
||||
\\ pop {pc}
|
||||
::: "memory");
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn __aeabi_uldivmod() callconv(.Naked) void {
|
||||
@setRuntimeSafety(false);
|
||||
// Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2
|
||||
asm volatile (
|
||||
\\ push {r4, lr}
|
||||
\\ sub sp, #16
|
||||
\\ add r4, sp, #8
|
||||
\\ str r4, [sp]
|
||||
\\ bl __udivmoddi4
|
||||
\\ ldr r2, [sp, #8]
|
||||
\\ ldr r3, [sp, #12]
|
||||
\\ add sp, #16
|
||||
\\ pop {r4, pc}
|
||||
::: "memory");
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn __aeabi_idivmod() callconv(.Naked) void {
|
||||
@setRuntimeSafety(false);
|
||||
// Divide r0 by r1; the quotient goes in r0, the remainder in r1
|
||||
asm volatile (
|
||||
\\ push {lr}
|
||||
\\ sub sp, #4
|
||||
\\ mov r2, sp
|
||||
\\ bl __divmodsi4
|
||||
\\ ldr r1, [sp]
|
||||
\\ add sp, #4
|
||||
\\ pop {pc}
|
||||
::: "memory");
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn __aeabi_ldivmod() callconv(.Naked) void {
|
||||
@setRuntimeSafety(false);
|
||||
// Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2
|
||||
asm volatile (
|
||||
\\ push {r4, lr}
|
||||
\\ sub sp, #16
|
||||
\\ add r4, sp, #8
|
||||
\\ str r4, [sp]
|
||||
\\ bl __divmoddi4
|
||||
\\ ldr r2, [sp, #8]
|
||||
\\ ldr r3, [sp, #12]
|
||||
\\ add sp, #16
|
||||
\\ pop {r4, pc}
|
||||
::: "memory");
|
||||
unreachable;
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
|
||||
const cpu = builtin.cpu;
|
||||
const arch = cpu.arch;
|
||||
const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
|
||||
pub const panic = @import("common.zig").panic;
|
||||
|
||||
// This parameter is true iff the target architecture supports the bare minimum
|
||||
// to implement the atomic load/store intrinsics.
|
||||
@ -24,6 +25,11 @@ const supports_atomic_ops = switch (arch) {
|
||||
// load/store atomically.
|
||||
// Objects bigger than this threshold require the use of a lock.
|
||||
const largest_atomic_size = switch (arch) {
|
||||
// On SPARC systems that lacks CAS and/or swap instructions, the only
|
||||
// available atomic operation is a test-and-set (`ldstub`), so we force
|
||||
// every atomic memory access to go through the lock.
|
||||
.sparc, .sparcel => if (cpu.features.featureSetHas(.hasleoncasa)) @sizeOf(usize) else 0,
|
||||
|
||||
// XXX: On x86/x86_64 we could check the presence of cmpxchg8b/cmpxchg16b
|
||||
// and set this parameter accordingly.
|
||||
else => @sizeOf(usize),
|
||||
@ -36,20 +42,44 @@ const SpinlockTable = struct {
|
||||
const max_spinlocks = 64;
|
||||
|
||||
const Spinlock = struct {
|
||||
// SPARC ldstub instruction will write a 255 into the memory location.
|
||||
// We'll use that as a sign that the lock is currently held.
|
||||
// See also: Section B.7 in SPARCv8 spec & A.29 in SPARCv9 spec.
|
||||
const sparc_lock: type = enum(u8) { Unlocked = 0, Locked = 255 };
|
||||
const other_lock: type = enum(usize) { Unlocked = 0, Locked };
|
||||
|
||||
// Prevent false sharing by providing enough padding between two
|
||||
// consecutive spinlock elements
|
||||
v: enum(usize) { Unlocked = 0, Locked } align(cache_line_size) = .Unlocked,
|
||||
v: if (arch.isSPARC()) sparc_lock else other_lock align(cache_line_size) = .Unlocked,
|
||||
|
||||
fn acquire(self: *@This()) void {
|
||||
while (true) {
|
||||
switch (@atomicRmw(@TypeOf(self.v), &self.v, .Xchg, .Locked, .Acquire)) {
|
||||
const flag = if (comptime arch.isSPARC()) flag: {
|
||||
break :flag asm volatile ("ldstub [%[addr]], %[flag]"
|
||||
: [flag] "=r" (-> @TypeOf(self.v)),
|
||||
: [addr] "r" (&self.v),
|
||||
: "memory"
|
||||
);
|
||||
} else flag: {
|
||||
break :flag @atomicRmw(@TypeOf(self.v), &self.v, .Xchg, .Locked, .Acquire);
|
||||
};
|
||||
|
||||
switch (flag) {
|
||||
.Unlocked => break,
|
||||
.Locked => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
fn release(self: *@This()) void {
|
||||
@atomicStore(@TypeOf(self.v), &self.v, .Unlocked, .Release);
|
||||
if (comptime arch.isSPARC()) {
|
||||
_ = asm volatile ("clrb [%[addr]]"
|
||||
:
|
||||
: [addr] "r" (&self.v),
|
||||
: "memory"
|
||||
);
|
||||
} else {
|
||||
@atomicStore(@TypeOf(self.v), &self.v, .Unlocked, .Release);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,7 +1,20 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
const abi = builtin.abi;
|
||||
const common = @import("common.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (arch == .i386 and abi == .msvc) {
|
||||
// Don't let LLVM apply the stdcall name mangling on those MSVC builtins
|
||||
@export(_alldiv, .{ .name = "\x01__alldiv", .linkage = common.linkage });
|
||||
@export(_aulldiv, .{ .name = "\x01__aulldiv", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _alldiv(a: i64, b: i64) callconv(.Stdcall) i64 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
const s_a = a >> (64 - 1);
|
||||
const s_b = b >> (64 - 1);
|
||||
|
||||
@ -1,7 +1,20 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
const abi = builtin.abi;
|
||||
const common = @import("common.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (arch == .i386 and abi == .msvc) {
|
||||
// Don't let LLVM apply the stdcall name mangling on those MSVC builtins
|
||||
@export(_allrem, .{ .name = "\x01__allrem", .linkage = common.linkage });
|
||||
@export(_aullrem, .{ .name = "\x01__aullrem", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _allrem(a: i64, b: i64) callconv(.Stdcall) i64 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
const s_a = a >> (64 - 1);
|
||||
const s_b = b >> (64 - 1);
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const common = @import("common.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__bswapsi2, .{ .name = "__bswapsi2", .linkage = common.linkage });
|
||||
@export(__bswapdi2, .{ .name = "__bswapdi2", .linkage = common.linkage });
|
||||
@export(__bswapti2, .{ .name = "__bswapti2", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
// bswap - byteswap
|
||||
// - bswapXi2 for unoptimized big and little endian
|
||||
@ -12,7 +21,6 @@ const builtin = @import("builtin");
|
||||
// 00 00 00 ff << 3*8 (rightmost byte)
|
||||
|
||||
inline fn bswapXi2(comptime T: type, a: T) T {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
switch (@bitSizeOf(T)) {
|
||||
32 => {
|
||||
// zig fmt: off
|
||||
180
lib/compiler_rt/ceil.zig
Normal file
180
lib/compiler_rt/ceil.zig
Normal file
@ -0,0 +1,180 @@
|
||||
//! Ported from musl, which is MIT licensed.
|
||||
//! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
|
||||
//!
|
||||
//! https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c
|
||||
//! https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
const math = std.math;
|
||||
const expect = std.testing.expect;
|
||||
const common = @import("common.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__ceilh, .{ .name = "__ceilh", .linkage = common.linkage });
|
||||
@export(ceilf, .{ .name = "ceilf", .linkage = common.linkage });
|
||||
@export(ceil, .{ .name = "ceil", .linkage = common.linkage });
|
||||
@export(__ceilx, .{ .name = "__ceilx", .linkage = common.linkage });
|
||||
const ceilq_sym_name = if (common.want_ppc_abi) "ceilf128" else "ceilq";
|
||||
@export(ceilq, .{ .name = ceilq_sym_name, .linkage = common.linkage });
|
||||
@export(ceill, .{ .name = "ceill", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
pub fn __ceilh(x: f16) callconv(.C) f16 {
|
||||
// TODO: more efficient implementation
|
||||
return @floatCast(f16, ceilf(x));
|
||||
}
|
||||
|
||||
pub fn ceilf(x: f32) callconv(.C) f32 {
|
||||
var u = @bitCast(u32, x);
|
||||
var e = @intCast(i32, (u >> 23) & 0xFF) - 0x7F;
|
||||
var m: u32 = undefined;
|
||||
|
||||
// TODO: Shouldn't need this explicit check.
|
||||
if (x == 0.0) {
|
||||
return x;
|
||||
}
|
||||
|
||||
if (e >= 23) {
|
||||
return x;
|
||||
} else if (e >= 0) {
|
||||
m = @as(u32, 0x007FFFFF) >> @intCast(u5, e);
|
||||
if (u & m == 0) {
|
||||
return x;
|
||||
}
|
||||
math.doNotOptimizeAway(x + 0x1.0p120);
|
||||
if (u >> 31 == 0) {
|
||||
u += m;
|
||||
}
|
||||
u &= ~m;
|
||||
return @bitCast(f32, u);
|
||||
} else {
|
||||
math.doNotOptimizeAway(x + 0x1.0p120);
|
||||
if (u >> 31 != 0) {
|
||||
return -0.0;
|
||||
} else {
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ceil(x: f64) callconv(.C) f64 {
|
||||
const f64_toint = 1.0 / math.floatEps(f64);
|
||||
|
||||
const u = @bitCast(u64, x);
|
||||
const e = (u >> 52) & 0x7FF;
|
||||
var y: f64 = undefined;
|
||||
|
||||
if (e >= 0x3FF + 52 or x == 0) {
|
||||
return x;
|
||||
}
|
||||
|
||||
if (u >> 63 != 0) {
|
||||
y = x - f64_toint + f64_toint - x;
|
||||
} else {
|
||||
y = x + f64_toint - f64_toint - x;
|
||||
}
|
||||
|
||||
if (e <= 0x3FF - 1) {
|
||||
math.doNotOptimizeAway(y);
|
||||
if (u >> 63 != 0) {
|
||||
return -0.0;
|
||||
} else {
|
||||
return 1.0;
|
||||
}
|
||||
} else if (y < 0) {
|
||||
return x + y + 1;
|
||||
} else {
|
||||
return x + y;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __ceilx(x: f80) callconv(.C) f80 {
|
||||
// TODO: more efficient implementation
|
||||
return @floatCast(f80, ceilq(x));
|
||||
}
|
||||
|
||||
pub fn ceilq(x: f128) callconv(.C) f128 {
|
||||
const f128_toint = 1.0 / math.floatEps(f128);
|
||||
|
||||
const u = @bitCast(u128, x);
|
||||
const e = (u >> 112) & 0x7FFF;
|
||||
var y: f128 = undefined;
|
||||
|
||||
if (e >= 0x3FFF + 112 or x == 0) return x;
|
||||
|
||||
if (u >> 127 != 0) {
|
||||
y = x - f128_toint + f128_toint - x;
|
||||
} else {
|
||||
y = x + f128_toint - f128_toint - x;
|
||||
}
|
||||
|
||||
if (e <= 0x3FFF - 1) {
|
||||
math.doNotOptimizeAway(y);
|
||||
if (u >> 127 != 0) {
|
||||
return -0.0;
|
||||
} else {
|
||||
return 1.0;
|
||||
}
|
||||
} else if (y < 0) {
|
||||
return x + y + 1;
|
||||
} else {
|
||||
return x + y;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ceill(x: c_longdouble) callconv(.C) c_longdouble {
|
||||
switch (@typeInfo(c_longdouble).Float.bits) {
|
||||
16 => return __ceilh(x),
|
||||
32 => return ceilf(x),
|
||||
64 => return ceil(x),
|
||||
80 => return __ceilx(x),
|
||||
128 => return ceilq(x),
|
||||
else => @compileError("unreachable"),
|
||||
}
|
||||
}
|
||||
|
||||
test "ceil32" {
|
||||
try expect(ceilf(1.3) == 2.0);
|
||||
try expect(ceilf(-1.3) == -1.0);
|
||||
try expect(ceilf(0.2) == 1.0);
|
||||
}
|
||||
|
||||
test "ceil64" {
|
||||
try expect(ceil(1.3) == 2.0);
|
||||
try expect(ceil(-1.3) == -1.0);
|
||||
try expect(ceil(0.2) == 1.0);
|
||||
}
|
||||
|
||||
test "ceil128" {
|
||||
try expect(ceilq(1.3) == 2.0);
|
||||
try expect(ceilq(-1.3) == -1.0);
|
||||
try expect(ceilq(0.2) == 1.0);
|
||||
}
|
||||
|
||||
test "ceil32.special" {
|
||||
try expect(ceilf(0.0) == 0.0);
|
||||
try expect(ceilf(-0.0) == -0.0);
|
||||
try expect(math.isPositiveInf(ceilf(math.inf(f32))));
|
||||
try expect(math.isNegativeInf(ceilf(-math.inf(f32))));
|
||||
try expect(math.isNan(ceilf(math.nan(f32))));
|
||||
}
|
||||
|
||||
test "ceil64.special" {
|
||||
try expect(ceil(0.0) == 0.0);
|
||||
try expect(ceil(-0.0) == -0.0);
|
||||
try expect(math.isPositiveInf(ceil(math.inf(f64))));
|
||||
try expect(math.isNegativeInf(ceil(-math.inf(f64))));
|
||||
try expect(math.isNan(ceil(math.nan(f64))));
|
||||
}
|
||||
|
||||
test "ceil128.special" {
|
||||
try expect(ceilq(0.0) == 0.0);
|
||||
try expect(ceilq(-0.0) == -0.0);
|
||||
try expect(math.isPositiveInf(ceilq(math.inf(f128))));
|
||||
try expect(math.isNegativeInf(ceilq(-math.inf(f128))));
|
||||
try expect(math.isNan(ceilq(math.nan(f128))));
|
||||
}
|
||||
@ -2,6 +2,7 @@ const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
const os = builtin.os.tag;
|
||||
pub const panic = @import("common.zig").panic;
|
||||
|
||||
// Ported from llvm-project d32170dbd5b0d54436537b6b75beaf44324e0c28
|
||||
|
||||
@ -10,7 +11,13 @@ const os = builtin.os.tag;
|
||||
// It is expected to invalidate the instruction cache for the
|
||||
// specified range.
|
||||
|
||||
pub fn clear_cache(start: usize, end: usize) callconv(.C) void {
|
||||
comptime {
|
||||
if (builtin.zig_backend != .stage2_llvm) {
|
||||
_ = clear_cache;
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_cache(start: usize, end: usize) callconv(.C) void {
|
||||
const x86 = switch (arch) {
|
||||
.i386, .x86_64 => true,
|
||||
else => false,
|
||||
@ -36,7 +43,7 @@ pub fn clear_cache(start: usize, end: usize) callconv(.C) void {
|
||||
else => false,
|
||||
};
|
||||
const sparc = switch (arch) {
|
||||
.sparc, .sparcv9, .sparcel => true,
|
||||
.sparc, .sparc64, .sparcel => true,
|
||||
else => false,
|
||||
};
|
||||
const apple = switch (os) {
|
||||
@ -1,14 +1,26 @@
|
||||
const builtin = @import("builtin");
|
||||
const clz = @import("count0bits.zig");
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__clzsi2(a: u32, expected: i32) !void {
|
||||
// XXX At high optimization levels this test may be horribly miscompiled if
|
||||
// one of the naked implementations is selected.
|
||||
var nakedClzsi2 = clz.__clzsi2;
|
||||
var actualClzsi2 = @ptrCast(fn (a: i32) callconv(.C) i32, nakedClzsi2);
|
||||
var x = @bitCast(i32, a);
|
||||
var result = actualClzsi2(x);
|
||||
try testing.expectEqual(expected, result);
|
||||
// stage1 and stage2 diverge on function pointer semantics
|
||||
switch (builtin.zig_backend) {
|
||||
.stage1 => {
|
||||
// Use of `var` here is working around a stage1 bug.
|
||||
var nakedClzsi2 = clz.__clzsi2;
|
||||
var actualClzsi2 = @ptrCast(fn (a: i32) callconv(.C) i32, nakedClzsi2);
|
||||
var x = @bitCast(i32, a);
|
||||
var result = actualClzsi2(x);
|
||||
try testing.expectEqual(expected, result);
|
||||
},
|
||||
else => {
|
||||
const nakedClzsi2 = clz.__clzsi2;
|
||||
const actualClzsi2 = @ptrCast(*const fn (a: i32) callconv(.C) i32, &nakedClzsi2);
|
||||
const x = @bitCast(i32, a);
|
||||
const result = actualClzsi2(x);
|
||||
try testing.expectEqual(expected, result);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
test "clzsi2" {
|
||||
@ -1,5 +1,18 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
const common = @import("common.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__cmpsi2, .{ .name = "__cmpsi2", .linkage = common.linkage });
|
||||
@export(__cmpdi2, .{ .name = "__cmpdi2", .linkage = common.linkage });
|
||||
@export(__cmpti2, .{ .name = "__cmpti2", .linkage = common.linkage });
|
||||
@export(__ucmpsi2, .{ .name = "__ucmpsi2", .linkage = common.linkage });
|
||||
@export(__ucmpdi2, .{ .name = "__ucmpdi2", .linkage = common.linkage });
|
||||
@export(__ucmpti2, .{ .name = "__ucmpti2", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
// cmp - signed compare
|
||||
// - cmpXi2_generic for unoptimized little and big endian
|
||||
@ -12,7 +25,6 @@ const builtin = @import("builtin");
|
||||
// a > b => 2
|
||||
|
||||
inline fn XcmpXi2(comptime T: type, a: T, b: T) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
var cmp1: i32 = 0;
|
||||
var cmp2: i32 = 0;
|
||||
if (a > b)
|
||||
68
lib/compiler_rt/cmpdf2.zig
Normal file
68
lib/compiler_rt/cmpdf2.zig
Normal file
@ -0,0 +1,68 @@
|
||||
///! The quoted behavior definitions are from
|
||||
///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
|
||||
const common = @import("./common.zig");
|
||||
const comparef = @import("./comparef.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (common.want_aeabi) {
|
||||
@export(__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = common.linkage });
|
||||
@export(__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = common.linkage });
|
||||
@export(__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = common.linkage });
|
||||
} else {
|
||||
@export(__eqdf2, .{ .name = "__eqdf2", .linkage = common.linkage });
|
||||
@export(__nedf2, .{ .name = "__nedf2", .linkage = common.linkage });
|
||||
@export(__ledf2, .{ .name = "__ledf2", .linkage = common.linkage });
|
||||
@export(__cmpdf2, .{ .name = "__cmpdf2", .linkage = common.linkage });
|
||||
@export(__ltdf2, .{ .name = "__ltdf2", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
|
||||
/// if a is greater than b, they return 1; and if a and b are equal they return 0.
|
||||
/// If either argument is NaN they return 1..."
|
||||
///
|
||||
/// Note that this matches the definition of `__ledf2`, `__eqdf2`, `__nedf2`, `__cmpdf2`,
|
||||
/// and `__ltdf2`.
|
||||
fn __cmpdf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
return @enumToInt(comparef.cmpf2(f64, comparef.LE, a, b));
|
||||
}
|
||||
|
||||
/// "These functions return a value less than or equal to zero if neither argument is NaN,
|
||||
/// and a is less than or equal to b."
|
||||
pub fn __ledf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
return __cmpdf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return zero if neither argument is NaN, and a and b are equal."
|
||||
/// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined
|
||||
/// to have the same return value.
|
||||
pub fn __eqdf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
return __cmpdf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
|
||||
/// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined
|
||||
/// to have the same return value.
|
||||
pub fn __nedf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
return __cmpdf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return a value less than zero if neither argument is NaN, and a
|
||||
/// is strictly less than b."
|
||||
pub fn __ltdf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
return __cmpdf2(a, b);
|
||||
}
|
||||
|
||||
fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.AAPCS) i32 {
|
||||
return @boolToInt(comparef.cmpf2(f64, comparef.LE, a, b) == .Equal);
|
||||
}
|
||||
|
||||
fn __aeabi_dcmplt(a: f64, b: f64) callconv(.AAPCS) i32 {
|
||||
return @boolToInt(comparef.cmpf2(f64, comparef.LE, a, b) == .Less);
|
||||
}
|
||||
|
||||
fn __aeabi_dcmple(a: f64, b: f64) callconv(.AAPCS) i32 {
|
||||
return @boolToInt(comparef.cmpf2(f64, comparef.LE, a, b) != .Greater);
|
||||
}
|
||||
68
lib/compiler_rt/cmpsf2.zig
Normal file
68
lib/compiler_rt/cmpsf2.zig
Normal file
@ -0,0 +1,68 @@
|
||||
///! The quoted behavior definitions are from
|
||||
///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
|
||||
const common = @import("./common.zig");
|
||||
const comparef = @import("./comparef.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (common.want_aeabi) {
|
||||
@export(__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = common.linkage });
|
||||
@export(__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = common.linkage });
|
||||
@export(__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = common.linkage });
|
||||
} else {
|
||||
@export(__eqsf2, .{ .name = "__eqsf2", .linkage = common.linkage });
|
||||
@export(__nesf2, .{ .name = "__nesf2", .linkage = common.linkage });
|
||||
@export(__lesf2, .{ .name = "__lesf2", .linkage = common.linkage });
|
||||
@export(__cmpsf2, .{ .name = "__cmpsf2", .linkage = common.linkage });
|
||||
@export(__ltsf2, .{ .name = "__ltsf2", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
|
||||
/// if a is greater than b, they return 1; and if a and b are equal they return 0.
|
||||
/// If either argument is NaN they return 1..."
|
||||
///
|
||||
/// Note that this matches the definition of `__lesf2`, `__eqsf2`, `__nesf2`, `__cmpsf2`,
|
||||
/// and `__ltsf2`.
|
||||
fn __cmpsf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
return @enumToInt(comparef.cmpf2(f32, comparef.LE, a, b));
|
||||
}
|
||||
|
||||
/// "These functions return a value less than or equal to zero if neither argument is NaN,
|
||||
/// and a is less than or equal to b."
|
||||
pub fn __lesf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
return __cmpsf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return zero if neither argument is NaN, and a and b are equal."
|
||||
/// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined
|
||||
/// to have the same return value.
|
||||
pub fn __eqsf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
return __cmpsf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
|
||||
/// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined
|
||||
/// to have the same return value.
|
||||
pub fn __nesf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
return __cmpsf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return a value less than zero if neither argument is NaN, and a
|
||||
/// is strictly less than b."
|
||||
pub fn __ltsf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
return __cmpsf2(a, b);
|
||||
}
|
||||
|
||||
fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.AAPCS) i32 {
|
||||
return @boolToInt(comparef.cmpf2(f32, comparef.LE, a, b) == .Equal);
|
||||
}
|
||||
|
||||
fn __aeabi_fcmplt(a: f32, b: f32) callconv(.AAPCS) i32 {
|
||||
return @boolToInt(comparef.cmpf2(f32, comparef.LE, a, b) == .Less);
|
||||
}
|
||||
|
||||
fn __aeabi_fcmple(a: f32, b: f32) callconv(.AAPCS) i32 {
|
||||
return @boolToInt(comparef.cmpf2(f32, comparef.LE, a, b) != .Greater);
|
||||
}
|
||||
122
lib/compiler_rt/cmptf2.zig
Normal file
122
lib/compiler_rt/cmptf2.zig
Normal file
@ -0,0 +1,122 @@
|
||||
///! The quoted behavior definitions are from
|
||||
///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
|
||||
const common = @import("./common.zig");
|
||||
const comparef = @import("./comparef.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (common.want_ppc_abi) {
|
||||
@export(__eqkf2, .{ .name = "__eqkf2", .linkage = common.linkage });
|
||||
@export(__nekf2, .{ .name = "__nekf2", .linkage = common.linkage });
|
||||
@export(__ltkf2, .{ .name = "__ltkf2", .linkage = common.linkage });
|
||||
@export(__lekf2, .{ .name = "__lekf2", .linkage = common.linkage });
|
||||
} else if (common.want_sparc_abi) {
|
||||
@export(_Qp_cmp, .{ .name = "_Qp_cmp", .linkage = common.linkage });
|
||||
@export(_Qp_feq, .{ .name = "_Qp_feq", .linkage = common.linkage });
|
||||
@export(_Qp_fne, .{ .name = "_Qp_fne", .linkage = common.linkage });
|
||||
@export(_Qp_flt, .{ .name = "_Qp_flt", .linkage = common.linkage });
|
||||
@export(_Qp_fle, .{ .name = "_Qp_fle", .linkage = common.linkage });
|
||||
@export(_Qp_fgt, .{ .name = "_Qp_fgt", .linkage = common.linkage });
|
||||
@export(_Qp_fge, .{ .name = "_Qp_fge", .linkage = common.linkage });
|
||||
} else {
|
||||
@export(__eqtf2, .{ .name = "__eqtf2", .linkage = common.linkage });
|
||||
@export(__netf2, .{ .name = "__netf2", .linkage = common.linkage });
|
||||
@export(__letf2, .{ .name = "__letf2", .linkage = common.linkage });
|
||||
@export(__cmptf2, .{ .name = "__cmptf2", .linkage = common.linkage });
|
||||
@export(__lttf2, .{ .name = "__lttf2", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
|
||||
/// if a is greater than b, they return 1; and if a and b are equal they return 0.
|
||||
/// If either argument is NaN they return 1..."
|
||||
///
|
||||
/// Note that this matches the definition of `__letf2`, `__eqtf2`, `__netf2`, `__cmptf2`,
|
||||
/// and `__lttf2`.
|
||||
fn __cmptf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return @enumToInt(comparef.cmpf2(f128, comparef.LE, a, b));
|
||||
}
|
||||
|
||||
/// "These functions return a value less than or equal to zero if neither argument is NaN,
|
||||
/// and a is less than or equal to b."
|
||||
fn __letf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __cmptf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return zero if neither argument is NaN, and a and b are equal."
|
||||
/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined
|
||||
/// to have the same return value.
|
||||
fn __eqtf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __cmptf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
|
||||
/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined
|
||||
/// to have the same return value.
|
||||
fn __netf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __cmptf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return a value less than zero if neither argument is NaN, and a
|
||||
/// is strictly less than b."
|
||||
fn __lttf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __cmptf2(a, b);
|
||||
}
|
||||
|
||||
fn __eqkf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __cmptf2(a, b);
|
||||
}
|
||||
|
||||
fn __nekf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __cmptf2(a, b);
|
||||
}
|
||||
|
||||
fn __ltkf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __cmptf2(a, b);
|
||||
}
|
||||
|
||||
fn __lekf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __cmptf2(a, b);
|
||||
}
|
||||
|
||||
const SparcFCMP = enum(i32) {
|
||||
Equal = 0,
|
||||
Less = 1,
|
||||
Greater = 2,
|
||||
Unordered = 3,
|
||||
};
|
||||
|
||||
fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.C) i32 {
|
||||
return @enumToInt(comparef.cmpf2(f128, SparcFCMP, a.*, b.*));
|
||||
}
|
||||
|
||||
fn _Qp_feq(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||
return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) == .Equal;
|
||||
}
|
||||
|
||||
fn _Qp_fne(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||
return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) != .Equal;
|
||||
}
|
||||
|
||||
fn _Qp_flt(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||
return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) == .Less;
|
||||
}
|
||||
|
||||
fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||
return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) == .Greater;
|
||||
}
|
||||
|
||||
fn _Qp_fge(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||
return switch (@intToEnum(SparcFCMP, _Qp_cmp(a, b))) {
|
||||
.Equal, .Greater => true,
|
||||
.Less, .Unordered => false,
|
||||
};
|
||||
}
|
||||
|
||||
fn _Qp_fle(a: *const f128, b: *const f128) callconv(.C) bool {
|
||||
return switch (@intToEnum(SparcFCMP, _Qp_cmp(a, b))) {
|
||||
.Equal, .Less => true,
|
||||
.Greater, .Unordered => false,
|
||||
};
|
||||
}
|
||||
50
lib/compiler_rt/cmpxf2.zig
Normal file
50
lib/compiler_rt/cmpxf2.zig
Normal file
@ -0,0 +1,50 @@
|
||||
///! The quoted behavior definitions are from
|
||||
///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines
|
||||
const common = @import("./common.zig");
|
||||
const comparef = @import("./comparef.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__eqxf2, .{ .name = "__eqxf2", .linkage = common.linkage });
|
||||
@export(__nexf2, .{ .name = "__nexf2", .linkage = common.linkage });
|
||||
@export(__lexf2, .{ .name = "__lexf2", .linkage = common.linkage });
|
||||
@export(__cmpxf2, .{ .name = "__cmpxf2", .linkage = common.linkage });
|
||||
@export(__ltxf2, .{ .name = "__ltxf2", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
|
||||
/// if a is greater than b, they return 1; and if a and b are equal they return 0.
|
||||
/// If either argument is NaN they return 1..."
|
||||
///
|
||||
/// Note that this matches the definition of `__lexf2`, `__eqxf2`, `__nexf2`, `__cmpxf2`,
|
||||
/// and `__ltxf2`.
|
||||
fn __cmpxf2(a: f80, b: f80) callconv(.C) i32 {
|
||||
return @enumToInt(comparef.cmp_f80(comparef.LE, a, b));
|
||||
}
|
||||
|
||||
/// "These functions return a value less than or equal to zero if neither argument is NaN,
|
||||
/// and a is less than or equal to b."
|
||||
fn __lexf2(a: f80, b: f80) callconv(.C) i32 {
|
||||
return __cmpxf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return zero if neither argument is NaN, and a and b are equal."
|
||||
/// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined
|
||||
/// to have the same return value.
|
||||
fn __eqxf2(a: f80, b: f80) callconv(.C) i32 {
|
||||
return __cmpxf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
|
||||
/// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined
|
||||
/// to have the same return value.
|
||||
fn __nexf2(a: f80, b: f80) callconv(.C) i32 {
|
||||
return __cmpxf2(a, b);
|
||||
}
|
||||
|
||||
/// "These functions return a value less than zero if neither argument is NaN, and a
|
||||
/// is strictly less than b."
|
||||
fn __ltxf2(a: f80, b: f80) callconv(.C) i32 {
|
||||
return __cmpxf2(a, b);
|
||||
}
|
||||
202
lib/compiler_rt/common.zig
Normal file
202
lib/compiler_rt/common.zig
Normal file
@ -0,0 +1,202 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
|
||||
pub const want_aeabi = switch (builtin.abi) {
|
||||
.eabi,
|
||||
.eabihf,
|
||||
.musleabi,
|
||||
.musleabihf,
|
||||
.gnueabi,
|
||||
.gnueabihf,
|
||||
=> switch (builtin.cpu.arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => true,
|
||||
else => false,
|
||||
},
|
||||
else => false,
|
||||
};
|
||||
pub const want_ppc_abi = builtin.cpu.arch.isPPC() or builtin.cpu.arch.isPPC64();
|
||||
|
||||
/// This governs whether to use these symbol names for f16/f32 conversions
|
||||
/// rather than the standard names:
|
||||
/// * __gnu_f2h_ieee
|
||||
/// * __gnu_h2f_ieee
|
||||
/// Known correct configurations:
|
||||
/// x86_64-freestanding-none => true
|
||||
/// x86_64-linux-none => true
|
||||
/// x86_64-linux-gnu => true
|
||||
/// x86_64-linux-musl => true
|
||||
/// x86_64-linux-eabi => true
|
||||
/// arm-linux-musleabihf => true
|
||||
/// arm-linux-gnueabihf => true
|
||||
/// arm-linux-eabihf => false
|
||||
/// wasm32-wasi-musl => false
|
||||
/// wasm32-freestanding-none => false
|
||||
/// x86_64-windows-gnu => true
|
||||
/// x86_64-windows-msvc => true
|
||||
/// any-macos-any => false
|
||||
pub const gnu_f16_abi = switch (builtin.cpu.arch) {
|
||||
.wasm32, .wasm64 => false,
|
||||
|
||||
.arm, .armeb, .thumb, .thumbeb => switch (builtin.abi) {
|
||||
.eabi, .eabihf => false,
|
||||
else => true,
|
||||
},
|
||||
|
||||
else => !builtin.os.tag.isDarwin(),
|
||||
};
|
||||
|
||||
pub const want_sparc_abi = builtin.cpu.arch.isSPARC();
|
||||
|
||||
// Avoid dragging in the runtime safety mechanisms into this .o file,
|
||||
// unless we're trying to test compiler-rt.
|
||||
pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn {
|
||||
_ = error_return_trace;
|
||||
if (builtin.is_test) {
|
||||
@setCold(true);
|
||||
std.debug.panic("{s}", .{msg});
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
/// AArch64 is the only ABI (at the moment) to support f16 arguments without the
|
||||
/// need for extending them to wider fp types.
|
||||
/// TODO remove this; do this type selection in the language rather than
|
||||
/// here in compiler-rt.
|
||||
pub const F16T = if (builtin.cpu.arch.isAARCH64()) f16 else u16;
|
||||
|
||||
pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
|
||||
switch (Z) {
|
||||
u16 => {
|
||||
// 16x16 --> 32 bit multiply
|
||||
const product = @as(u32, a) * @as(u32, b);
|
||||
hi.* = @intCast(u16, product >> 16);
|
||||
lo.* = @truncate(u16, product);
|
||||
},
|
||||
u32 => {
|
||||
// 32x32 --> 64 bit multiply
|
||||
const product = @as(u64, a) * @as(u64, b);
|
||||
hi.* = @truncate(u32, product >> 32);
|
||||
lo.* = @truncate(u32, product);
|
||||
},
|
||||
u64 => {
|
||||
const S = struct {
|
||||
fn loWord(x: u64) u64 {
|
||||
return @truncate(u32, x);
|
||||
}
|
||||
fn hiWord(x: u64) u64 {
|
||||
return @truncate(u32, x >> 32);
|
||||
}
|
||||
};
|
||||
// 64x64 -> 128 wide multiply for platforms that don't have such an operation;
|
||||
// many 64-bit platforms have this operation, but they tend to have hardware
|
||||
// floating-point, so we don't bother with a special case for them here.
|
||||
// Each of the component 32x32 -> 64 products
|
||||
const plolo: u64 = S.loWord(a) * S.loWord(b);
|
||||
const plohi: u64 = S.loWord(a) * S.hiWord(b);
|
||||
const philo: u64 = S.hiWord(a) * S.loWord(b);
|
||||
const phihi: u64 = S.hiWord(a) * S.hiWord(b);
|
||||
// Sum terms that contribute to lo in a way that allows us to get the carry
|
||||
const r0: u64 = S.loWord(plolo);
|
||||
const r1: u64 = S.hiWord(plolo) +% S.loWord(plohi) +% S.loWord(philo);
|
||||
lo.* = r0 +% (r1 << 32);
|
||||
// Sum terms contributing to hi with the carry from lo
|
||||
hi.* = S.hiWord(plohi) +% S.hiWord(philo) +% S.hiWord(r1) +% phihi;
|
||||
},
|
||||
u128 => {
|
||||
const Word_LoMask = @as(u64, 0x00000000ffffffff);
|
||||
const Word_HiMask = @as(u64, 0xffffffff00000000);
|
||||
const Word_FullMask = @as(u64, 0xffffffffffffffff);
|
||||
const S = struct {
|
||||
fn Word_1(x: u128) u64 {
|
||||
return @truncate(u32, x >> 96);
|
||||
}
|
||||
fn Word_2(x: u128) u64 {
|
||||
return @truncate(u32, x >> 64);
|
||||
}
|
||||
fn Word_3(x: u128) u64 {
|
||||
return @truncate(u32, x >> 32);
|
||||
}
|
||||
fn Word_4(x: u128) u64 {
|
||||
return @truncate(u32, x);
|
||||
}
|
||||
};
|
||||
// 128x128 -> 256 wide multiply for platforms that don't have such an operation;
|
||||
// many 64-bit platforms have this operation, but they tend to have hardware
|
||||
// floating-point, so we don't bother with a special case for them here.
|
||||
|
||||
const product11: u64 = S.Word_1(a) * S.Word_1(b);
|
||||
const product12: u64 = S.Word_1(a) * S.Word_2(b);
|
||||
const product13: u64 = S.Word_1(a) * S.Word_3(b);
|
||||
const product14: u64 = S.Word_1(a) * S.Word_4(b);
|
||||
const product21: u64 = S.Word_2(a) * S.Word_1(b);
|
||||
const product22: u64 = S.Word_2(a) * S.Word_2(b);
|
||||
const product23: u64 = S.Word_2(a) * S.Word_3(b);
|
||||
const product24: u64 = S.Word_2(a) * S.Word_4(b);
|
||||
const product31: u64 = S.Word_3(a) * S.Word_1(b);
|
||||
const product32: u64 = S.Word_3(a) * S.Word_2(b);
|
||||
const product33: u64 = S.Word_3(a) * S.Word_3(b);
|
||||
const product34: u64 = S.Word_3(a) * S.Word_4(b);
|
||||
const product41: u64 = S.Word_4(a) * S.Word_1(b);
|
||||
const product42: u64 = S.Word_4(a) * S.Word_2(b);
|
||||
const product43: u64 = S.Word_4(a) * S.Word_3(b);
|
||||
const product44: u64 = S.Word_4(a) * S.Word_4(b);
|
||||
|
||||
const sum0: u128 = @as(u128, product44);
|
||||
const sum1: u128 = @as(u128, product34) +%
|
||||
@as(u128, product43);
|
||||
const sum2: u128 = @as(u128, product24) +%
|
||||
@as(u128, product33) +%
|
||||
@as(u128, product42);
|
||||
const sum3: u128 = @as(u128, product14) +%
|
||||
@as(u128, product23) +%
|
||||
@as(u128, product32) +%
|
||||
@as(u128, product41);
|
||||
const sum4: u128 = @as(u128, product13) +%
|
||||
@as(u128, product22) +%
|
||||
@as(u128, product31);
|
||||
const sum5: u128 = @as(u128, product12) +%
|
||||
@as(u128, product21);
|
||||
const sum6: u128 = @as(u128, product11);
|
||||
|
||||
const r0: u128 = (sum0 & Word_FullMask) +%
|
||||
((sum1 & Word_LoMask) << 32);
|
||||
const r1: u128 = (sum0 >> 64) +%
|
||||
((sum1 >> 32) & Word_FullMask) +%
|
||||
(sum2 & Word_FullMask) +%
|
||||
((sum3 << 32) & Word_HiMask);
|
||||
|
||||
lo.* = r0 +% (r1 << 64);
|
||||
hi.* = (r1 >> 64) +%
|
||||
(sum1 >> 96) +%
|
||||
(sum2 >> 64) +%
|
||||
(sum3 >> 32) +%
|
||||
sum4 +%
|
||||
(sum5 << 32) +%
|
||||
(sum6 << 64);
|
||||
},
|
||||
else => @compileError("unsupported"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T).Float.bits)) i32 {
|
||||
const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
|
||||
const integerBit = @as(Z, 1) << std.math.floatFractionalBits(T);
|
||||
|
||||
const shift = @clz(Z, significand.*) - @clz(Z, integerBit);
|
||||
significand.* <<= @intCast(std.math.Log2Int(Z), shift);
|
||||
return @as(i32, 1) - shift;
|
||||
}
|
||||
|
||||
pub inline fn fneg(a: anytype) @TypeOf(a) {
|
||||
const F = @TypeOf(a);
|
||||
const bits = @typeInfo(F).Float.bits;
|
||||
const U = @Type(.{ .Int = .{
|
||||
.signedness = .unsigned,
|
||||
.bits = bits,
|
||||
} });
|
||||
const sign_bit_mask = @as(U, 1) << (bits - 1);
|
||||
const negated = @bitCast(U, a) ^ sign_bit_mask;
|
||||
return @bitCast(F, negated);
|
||||
}
|
||||
@ -6,7 +6,15 @@ const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
|
||||
const comparedf2 = @import("compareXf2.zig");
|
||||
const __eqdf2 = @import("./cmpdf2.zig").__eqdf2;
|
||||
const __ledf2 = @import("./cmpdf2.zig").__ledf2;
|
||||
const __ltdf2 = @import("./cmpdf2.zig").__ltdf2;
|
||||
const __nedf2 = @import("./cmpdf2.zig").__nedf2;
|
||||
|
||||
const __gedf2 = @import("./gedf2.zig").__gedf2;
|
||||
const __gtdf2 = @import("./gedf2.zig").__gtdf2;
|
||||
|
||||
const __unorddf2 = @import("./unorddf2.zig").__unorddf2;
|
||||
|
||||
const TestVector = struct {
|
||||
a: f64,
|
||||
@ -21,25 +29,25 @@ const TestVector = struct {
|
||||
};
|
||||
|
||||
fn test__cmpdf2(vector: TestVector) bool {
|
||||
if (comparedf2.__eqdf2(vector.a, vector.b) != vector.eqReference) {
|
||||
if (__eqdf2(vector.a, vector.b) != vector.eqReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparedf2.__gedf2(vector.a, vector.b) != vector.geReference) {
|
||||
if (__gedf2(vector.a, vector.b) != vector.geReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparedf2.__gtdf2(vector.a, vector.b) != vector.gtReference) {
|
||||
if (__gtdf2(vector.a, vector.b) != vector.gtReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparedf2.__ledf2(vector.a, vector.b) != vector.leReference) {
|
||||
if (__ledf2(vector.a, vector.b) != vector.leReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparedf2.__ltdf2(vector.a, vector.b) != vector.ltReference) {
|
||||
if (__ltdf2(vector.a, vector.b) != vector.ltReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparedf2.__nedf2(vector.a, vector.b) != vector.neReference) {
|
||||
if (__nedf2(vector.a, vector.b) != vector.neReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparedf2.__unorddf2(vector.a, vector.b) != vector.unReference) {
|
||||
if (__unorddf2(vector.a, vector.b) != vector.unReference) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
118
lib/compiler_rt/comparef.zig
Normal file
118
lib/compiler_rt/comparef.zig
Normal file
@ -0,0 +1,118 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const LE = enum(i32) {
|
||||
Less = -1,
|
||||
Equal = 0,
|
||||
Greater = 1,
|
||||
|
||||
const Unordered: LE = .Greater;
|
||||
};
|
||||
|
||||
pub const GE = enum(i32) {
|
||||
Less = -1,
|
||||
Equal = 0,
|
||||
Greater = 1,
|
||||
|
||||
const Unordered: GE = .Less;
|
||||
};
|
||||
|
||||
pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT {
|
||||
const bits = @typeInfo(T).Float.bits;
|
||||
const srep_t = std.meta.Int(.signed, bits);
|
||||
const rep_t = std.meta.Int(.unsigned, bits);
|
||||
|
||||
const significandBits = std.math.floatMantissaBits(T);
|
||||
const exponentBits = std.math.floatExponentBits(T);
|
||||
const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
|
||||
const absMask = signBit - 1;
|
||||
const infT = comptime std.math.inf(T);
|
||||
const infRep = @bitCast(rep_t, infT);
|
||||
|
||||
const aInt = @bitCast(srep_t, a);
|
||||
const bInt = @bitCast(srep_t, b);
|
||||
const aAbs = @bitCast(rep_t, aInt) & absMask;
|
||||
const bAbs = @bitCast(rep_t, bInt) & absMask;
|
||||
|
||||
// If either a or b is NaN, they are unordered.
|
||||
if (aAbs > infRep or bAbs > infRep) return RT.Unordered;
|
||||
|
||||
// If a and b are both zeros, they are equal.
|
||||
if ((aAbs | bAbs) == 0) return .Equal;
|
||||
|
||||
// If at least one of a and b is positive, we get the same result comparing
|
||||
// a and b as signed integers as we would with a floating-point compare.
|
||||
if ((aInt & bInt) >= 0) {
|
||||
if (aInt < bInt) {
|
||||
return .Less;
|
||||
} else if (aInt == bInt) {
|
||||
return .Equal;
|
||||
} else return .Greater;
|
||||
} else {
|
||||
// Otherwise, both are negative, so we need to flip the sense of the
|
||||
// comparison to get the correct result. (This assumes a twos- or ones-
|
||||
// complement integer representation; if integers are represented in a
|
||||
// sign-magnitude representation, then this flip is incorrect).
|
||||
if (aInt > bInt) {
|
||||
return .Less;
|
||||
} else if (aInt == bInt) {
|
||||
return .Equal;
|
||||
} else return .Greater;
|
||||
}
|
||||
}
|
||||
|
||||
pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT {
|
||||
const a_rep = std.math.break_f80(a);
|
||||
const b_rep = std.math.break_f80(b);
|
||||
const sig_bits = std.math.floatMantissaBits(f80);
|
||||
const int_bit = 0x8000000000000000;
|
||||
const sign_bit = 0x8000;
|
||||
const special_exp = 0x7FFF;
|
||||
|
||||
// If either a or b is NaN, they are unordered.
|
||||
if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or
|
||||
(b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0))
|
||||
return RT.Unordered;
|
||||
|
||||
// If a and b are both zeros, they are equal.
|
||||
if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0)
|
||||
return .Equal;
|
||||
|
||||
if (@boolToInt(a_rep.exp == b_rep.exp) & @boolToInt(a_rep.fraction == b_rep.fraction) != 0) {
|
||||
return .Equal;
|
||||
} else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) {
|
||||
// signs are different
|
||||
if (@bitCast(i16, a_rep.exp) < @bitCast(i16, b_rep.exp)) {
|
||||
return .Less;
|
||||
} else {
|
||||
return .Greater;
|
||||
}
|
||||
} else {
|
||||
const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits);
|
||||
const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits);
|
||||
if (a_fraction < b_fraction) {
|
||||
return .Less;
|
||||
} else {
|
||||
return .Greater;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 {
|
||||
const rep_t = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
|
||||
|
||||
const significandBits = std.math.floatMantissaBits(T);
|
||||
const exponentBits = std.math.floatExponentBits(T);
|
||||
const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
|
||||
const absMask = signBit - 1;
|
||||
const infRep = @bitCast(rep_t, std.math.inf(T));
|
||||
|
||||
const aAbs: rep_t = @bitCast(rep_t, a) & absMask;
|
||||
const bAbs: rep_t = @bitCast(rep_t, b) & absMask;
|
||||
|
||||
return @boolToInt(aAbs > infRep or bAbs > infRep);
|
||||
}
|
||||
|
||||
test {
|
||||
_ = @import("comparesf2_test.zig");
|
||||
_ = @import("comparedf2_test.zig");
|
||||
}
|
||||
@ -6,7 +6,15 @@ const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
|
||||
const comparesf2 = @import("compareXf2.zig");
|
||||
const __eqsf2 = @import("./cmpsf2.zig").__eqsf2;
|
||||
const __lesf2 = @import("./cmpsf2.zig").__lesf2;
|
||||
const __ltsf2 = @import("./cmpsf2.zig").__ltsf2;
|
||||
const __nesf2 = @import("./cmpsf2.zig").__nesf2;
|
||||
|
||||
const __gesf2 = @import("./gesf2.zig").__gesf2;
|
||||
const __gtsf2 = @import("./gesf2.zig").__gtsf2;
|
||||
|
||||
const __unordsf2 = @import("./unordsf2.zig").__unordsf2;
|
||||
|
||||
const TestVector = struct {
|
||||
a: f32,
|
||||
@ -21,25 +29,25 @@ const TestVector = struct {
|
||||
};
|
||||
|
||||
fn test__cmpsf2(vector: TestVector) bool {
|
||||
if (comparesf2.__eqsf2(vector.a, vector.b) != vector.eqReference) {
|
||||
if (__eqsf2(vector.a, vector.b) != vector.eqReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparesf2.__gesf2(vector.a, vector.b) != vector.geReference) {
|
||||
if (__gesf2(vector.a, vector.b) != vector.geReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparesf2.__gtsf2(vector.a, vector.b) != vector.gtReference) {
|
||||
if (__gtsf2(vector.a, vector.b) != vector.gtReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparesf2.__lesf2(vector.a, vector.b) != vector.leReference) {
|
||||
if (__lesf2(vector.a, vector.b) != vector.leReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparesf2.__ltsf2(vector.a, vector.b) != vector.ltReference) {
|
||||
if (__ltsf2(vector.a, vector.b) != vector.ltReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparesf2.__nesf2(vector.a, vector.b) != vector.neReference) {
|
||||
if (__nesf2(vector.a, vector.b) != vector.neReference) {
|
||||
return false;
|
||||
}
|
||||
if (comparesf2.__unordsf2(vector.a, vector.b) != vector.unReference) {
|
||||
if (__unordsf2(vector.a, vector.b) != vector.unReference) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
170
lib/compiler_rt/cos.zig
Normal file
170
lib/compiler_rt/cos.zig
Normal file
@ -0,0 +1,170 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
const math = std.math;
|
||||
const expect = std.testing.expect;
|
||||
const common = @import("common.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
const trig = @import("trig.zig");
|
||||
const rem_pio2 = @import("rem_pio2.zig").rem_pio2;
|
||||
const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;
|
||||
|
||||
comptime {
|
||||
@export(__cosh, .{ .name = "__cosh", .linkage = common.linkage });
|
||||
@export(cosf, .{ .name = "cosf", .linkage = common.linkage });
|
||||
@export(cos, .{ .name = "cos", .linkage = common.linkage });
|
||||
@export(__cosx, .{ .name = "__cosx", .linkage = common.linkage });
|
||||
const cosq_sym_name = if (common.want_ppc_abi) "cosf128" else "cosq";
|
||||
@export(cosq, .{ .name = cosq_sym_name, .linkage = common.linkage });
|
||||
@export(cosl, .{ .name = "cosl", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
pub fn __cosh(a: f16) callconv(.C) f16 {
|
||||
// TODO: more efficient implementation
|
||||
return @floatCast(f16, cosf(a));
|
||||
}
|
||||
|
||||
pub fn cosf(x: f32) callconv(.C) f32 {
|
||||
// Small multiples of pi/2 rounded to double precision.
|
||||
const c1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18
|
||||
const c2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18
|
||||
const c3pio2: f64 = 3.0 * math.pi / 2.0; // 0x4012D97C, 0x7F3321D2
|
||||
const c4pio2: f64 = 4.0 * math.pi / 2.0; // 0x401921FB, 0x54442D18
|
||||
|
||||
var ix = @bitCast(u32, x);
|
||||
const sign = ix >> 31 != 0;
|
||||
ix &= 0x7fffffff;
|
||||
|
||||
if (ix <= 0x3f490fda) { // |x| ~<= pi/4
|
||||
if (ix < 0x39800000) { // |x| < 2**-12
|
||||
// raise inexact if x != 0
|
||||
math.doNotOptimizeAway(x + 0x1p120);
|
||||
return 1.0;
|
||||
}
|
||||
return trig.__cosdf(x);
|
||||
}
|
||||
if (ix <= 0x407b53d1) { // |x| ~<= 5*pi/4
|
||||
if (ix > 0x4016cbe3) { // |x| ~> 3*pi/4
|
||||
return -trig.__cosdf(if (sign) x + c2pio2 else x - c2pio2);
|
||||
} else {
|
||||
if (sign) {
|
||||
return trig.__sindf(x + c1pio2);
|
||||
} else {
|
||||
return trig.__sindf(c1pio2 - x);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ix <= 0x40e231d5) { // |x| ~<= 9*pi/4
|
||||
if (ix > 0x40afeddf) { // |x| ~> 7*pi/4
|
||||
return trig.__cosdf(if (sign) x + c4pio2 else x - c4pio2);
|
||||
} else {
|
||||
if (sign) {
|
||||
return trig.__sindf(-x - c3pio2);
|
||||
} else {
|
||||
return trig.__sindf(x - c3pio2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cos(Inf or NaN) is NaN
|
||||
if (ix >= 0x7f800000) {
|
||||
return x - x;
|
||||
}
|
||||
|
||||
var y: f64 = undefined;
|
||||
const n = rem_pio2f(x, &y);
|
||||
return switch (n & 3) {
|
||||
0 => trig.__cosdf(y),
|
||||
1 => trig.__sindf(-y),
|
||||
2 => -trig.__cosdf(y),
|
||||
else => trig.__sindf(y),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn cos(x: f64) callconv(.C) f64 {
|
||||
var ix = @bitCast(u64, x) >> 32;
|
||||
ix &= 0x7fffffff;
|
||||
|
||||
// |x| ~< pi/4
|
||||
if (ix <= 0x3fe921fb) {
|
||||
if (ix < 0x3e46a09e) { // |x| < 2**-27 * sqrt(2)
|
||||
// raise inexact if x!=0
|
||||
math.doNotOptimizeAway(x + 0x1p120);
|
||||
return 1.0;
|
||||
}
|
||||
return trig.__cos(x, 0);
|
||||
}
|
||||
|
||||
// cos(Inf or NaN) is NaN
|
||||
if (ix >= 0x7ff00000) {
|
||||
return x - x;
|
||||
}
|
||||
|
||||
var y: [2]f64 = undefined;
|
||||
const n = rem_pio2(x, &y);
|
||||
return switch (n & 3) {
|
||||
0 => trig.__cos(y[0], y[1]),
|
||||
1 => -trig.__sin(y[0], y[1], 1),
|
||||
2 => -trig.__cos(y[0], y[1]),
|
||||
else => trig.__sin(y[0], y[1], 1),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn __cosx(a: f80) callconv(.C) f80 {
|
||||
// TODO: more efficient implementation
|
||||
return @floatCast(f80, cosq(a));
|
||||
}
|
||||
|
||||
pub fn cosq(a: f128) callconv(.C) f128 {
|
||||
// TODO: more correct implementation
|
||||
return cos(@floatCast(f64, a));
|
||||
}
|
||||
|
||||
pub fn cosl(x: c_longdouble) callconv(.C) c_longdouble {
|
||||
switch (@typeInfo(c_longdouble).Float.bits) {
|
||||
16 => return __cosh(x),
|
||||
32 => return cosf(x),
|
||||
64 => return cos(x),
|
||||
80 => return __cosx(x),
|
||||
128 => return cosq(x),
|
||||
else => @compileError("unreachable"),
|
||||
}
|
||||
}
|
||||
|
||||
test "cos32" {
|
||||
const epsilon = 0.00001;
|
||||
|
||||
try expect(math.approxEqAbs(f32, cosf(0.0), 1.0, epsilon));
|
||||
try expect(math.approxEqAbs(f32, cosf(0.2), 0.980067, epsilon));
|
||||
try expect(math.approxEqAbs(f32, cosf(0.8923), 0.627623, epsilon));
|
||||
try expect(math.approxEqAbs(f32, cosf(1.5), 0.070737, epsilon));
|
||||
try expect(math.approxEqAbs(f32, cosf(-1.5), 0.070737, epsilon));
|
||||
try expect(math.approxEqAbs(f32, cosf(37.45), 0.969132, epsilon));
|
||||
try expect(math.approxEqAbs(f32, cosf(89.123), 0.400798, epsilon));
|
||||
}
|
||||
|
||||
test "cos64" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(math.approxEqAbs(f64, cos(0.0), 1.0, epsilon));
|
||||
try expect(math.approxEqAbs(f64, cos(0.2), 0.980067, epsilon));
|
||||
try expect(math.approxEqAbs(f64, cos(0.8923), 0.627623, epsilon));
|
||||
try expect(math.approxEqAbs(f64, cos(1.5), 0.070737, epsilon));
|
||||
try expect(math.approxEqAbs(f64, cos(-1.5), 0.070737, epsilon));
|
||||
try expect(math.approxEqAbs(f64, cos(37.45), 0.969132, epsilon));
|
||||
try expect(math.approxEqAbs(f64, cos(89.123), 0.40080, epsilon));
|
||||
}
|
||||
|
||||
test "cos32.special" {
|
||||
try expect(math.isNan(cosf(math.inf(f32))));
|
||||
try expect(math.isNan(cosf(-math.inf(f32))));
|
||||
try expect(math.isNan(cosf(math.nan(f32))));
|
||||
}
|
||||
|
||||
test "cos64.special" {
|
||||
try expect(math.isNan(cos(math.inf(f64))));
|
||||
try expect(math.isNan(cos(-math.inf(f64))));
|
||||
try expect(math.isNan(cos(math.nan(f64))));
|
||||
}
|
||||
@ -1,5 +1,21 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
const common = @import("common.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__clzsi2, .{ .name = "__clzsi2", .linkage = common.linkage });
|
||||
@export(__clzdi2, .{ .name = "__clzdi2", .linkage = common.linkage });
|
||||
@export(__clzti2, .{ .name = "__clzti2", .linkage = common.linkage });
|
||||
@export(__ctzsi2, .{ .name = "__ctzsi2", .linkage = common.linkage });
|
||||
@export(__ctzdi2, .{ .name = "__ctzdi2", .linkage = common.linkage });
|
||||
@export(__ctzti2, .{ .name = "__ctzti2", .linkage = common.linkage });
|
||||
@export(__ffssi2, .{ .name = "__ffssi2", .linkage = common.linkage });
|
||||
@export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = common.linkage });
|
||||
@export(__ffsti2, .{ .name = "__ffsti2", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
// clz - count leading zeroes
|
||||
// - clzXi2 for unoptimized little and big endian
|
||||
@ -15,8 +31,6 @@ const builtin = @import("builtin");
|
||||
// - ffsXi2 for unoptimized little and big endian
|
||||
|
||||
inline fn clzXi2(comptime T: type, a: T) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
|
||||
var x = switch (@bitSizeOf(T)) {
|
||||
32 => @bitCast(u32, a),
|
||||
64 => @bitCast(u64, a),
|
||||
@ -154,8 +168,6 @@ pub fn __clzti2(a: i128) callconv(.C) i32 {
|
||||
}
|
||||
|
||||
inline fn ctzXi2(comptime T: type, a: T) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
|
||||
var x = switch (@bitSizeOf(T)) {
|
||||
32 => @bitCast(u32, a),
|
||||
64 => @bitCast(u64, a),
|
||||
@ -191,8 +203,6 @@ pub fn __ctzti2(a: i128) callconv(.C) i32 {
|
||||
}
|
||||
|
||||
inline fn ffsXi2(comptime T: type, a: T) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
|
||||
var x = switch (@bitSizeOf(T)) {
|
||||
32 => @bitCast(u32, a),
|
||||
64 => @bitCast(u64, a),
|
||||
@ -1,12 +1,35 @@
|
||||
// Ported from:
|
||||
//
|
||||
// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divdf3.c
|
||||
//! Ported from:
|
||||
//!
|
||||
//! https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divdf3.c
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
const is_test = builtin.is_test;
|
||||
const common = @import("common.zig");
|
||||
|
||||
const normalize = common.normalize;
|
||||
const wideMultiply = common.wideMultiply;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (common.want_aeabi) {
|
||||
@export(__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = common.linkage });
|
||||
} else {
|
||||
@export(__divdf3, .{ .name = "__divdf3", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return div(a, b);
|
||||
}
|
||||
|
||||
fn __aeabi_ddiv(a: f64, b: f64) callconv(.AAPCS) f64 {
|
||||
return div(a, b);
|
||||
}
|
||||
|
||||
inline fn div(a: f64, b: f64) f64 {
|
||||
const Z = std.meta.Int(.unsigned, 64);
|
||||
const SignedZ = std.meta.Int(.signed, 64);
|
||||
|
||||
@ -202,131 +225,6 @@ pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
switch (Z) {
|
||||
u32 => {
|
||||
// 32x32 --> 64 bit multiply
|
||||
const product = @as(u64, a) * @as(u64, b);
|
||||
hi.* = @truncate(u32, product >> 32);
|
||||
lo.* = @truncate(u32, product);
|
||||
},
|
||||
u64 => {
|
||||
const S = struct {
|
||||
fn loWord(x: u64) u64 {
|
||||
return @truncate(u32, x);
|
||||
}
|
||||
fn hiWord(x: u64) u64 {
|
||||
return @truncate(u32, x >> 32);
|
||||
}
|
||||
};
|
||||
// 64x64 -> 128 wide multiply for platforms that don't have such an operation;
|
||||
// many 64-bit platforms have this operation, but they tend to have hardware
|
||||
// floating-point, so we don't bother with a special case for them here.
|
||||
// Each of the component 32x32 -> 64 products
|
||||
const plolo: u64 = S.loWord(a) * S.loWord(b);
|
||||
const plohi: u64 = S.loWord(a) * S.hiWord(b);
|
||||
const philo: u64 = S.hiWord(a) * S.loWord(b);
|
||||
const phihi: u64 = S.hiWord(a) * S.hiWord(b);
|
||||
// Sum terms that contribute to lo in a way that allows us to get the carry
|
||||
const r0: u64 = S.loWord(plolo);
|
||||
const r1: u64 = S.hiWord(plolo) +% S.loWord(plohi) +% S.loWord(philo);
|
||||
lo.* = r0 +% (r1 << 32);
|
||||
// Sum terms contributing to hi with the carry from lo
|
||||
hi.* = S.hiWord(plohi) +% S.hiWord(philo) +% S.hiWord(r1) +% phihi;
|
||||
},
|
||||
u128 => {
|
||||
const Word_LoMask = @as(u64, 0x00000000ffffffff);
|
||||
const Word_HiMask = @as(u64, 0xffffffff00000000);
|
||||
const Word_FullMask = @as(u64, 0xffffffffffffffff);
|
||||
const S = struct {
|
||||
fn Word_1(x: u128) u64 {
|
||||
return @truncate(u32, x >> 96);
|
||||
}
|
||||
fn Word_2(x: u128) u64 {
|
||||
return @truncate(u32, x >> 64);
|
||||
}
|
||||
fn Word_3(x: u128) u64 {
|
||||
return @truncate(u32, x >> 32);
|
||||
}
|
||||
fn Word_4(x: u128) u64 {
|
||||
return @truncate(u32, x);
|
||||
}
|
||||
};
|
||||
// 128x128 -> 256 wide multiply for platforms that don't have such an operation;
|
||||
// many 64-bit platforms have this operation, but they tend to have hardware
|
||||
// floating-point, so we don't bother with a special case for them here.
|
||||
|
||||
const product11: u64 = S.Word_1(a) * S.Word_1(b);
|
||||
const product12: u64 = S.Word_1(a) * S.Word_2(b);
|
||||
const product13: u64 = S.Word_1(a) * S.Word_3(b);
|
||||
const product14: u64 = S.Word_1(a) * S.Word_4(b);
|
||||
const product21: u64 = S.Word_2(a) * S.Word_1(b);
|
||||
const product22: u64 = S.Word_2(a) * S.Word_2(b);
|
||||
const product23: u64 = S.Word_2(a) * S.Word_3(b);
|
||||
const product24: u64 = S.Word_2(a) * S.Word_4(b);
|
||||
const product31: u64 = S.Word_3(a) * S.Word_1(b);
|
||||
const product32: u64 = S.Word_3(a) * S.Word_2(b);
|
||||
const product33: u64 = S.Word_3(a) * S.Word_3(b);
|
||||
const product34: u64 = S.Word_3(a) * S.Word_4(b);
|
||||
const product41: u64 = S.Word_4(a) * S.Word_1(b);
|
||||
const product42: u64 = S.Word_4(a) * S.Word_2(b);
|
||||
const product43: u64 = S.Word_4(a) * S.Word_3(b);
|
||||
const product44: u64 = S.Word_4(a) * S.Word_4(b);
|
||||
|
||||
const sum0: u128 = @as(u128, product44);
|
||||
const sum1: u128 = @as(u128, product34) +%
|
||||
@as(u128, product43);
|
||||
const sum2: u128 = @as(u128, product24) +%
|
||||
@as(u128, product33) +%
|
||||
@as(u128, product42);
|
||||
const sum3: u128 = @as(u128, product14) +%
|
||||
@as(u128, product23) +%
|
||||
@as(u128, product32) +%
|
||||
@as(u128, product41);
|
||||
const sum4: u128 = @as(u128, product13) +%
|
||||
@as(u128, product22) +%
|
||||
@as(u128, product31);
|
||||
const sum5: u128 = @as(u128, product12) +%
|
||||
@as(u128, product21);
|
||||
const sum6: u128 = @as(u128, product11);
|
||||
|
||||
const r0: u128 = (sum0 & Word_FullMask) +%
|
||||
((sum1 & Word_LoMask) << 32);
|
||||
const r1: u128 = (sum0 >> 64) +%
|
||||
((sum1 >> 32) & Word_FullMask) +%
|
||||
(sum2 & Word_FullMask) +%
|
||||
((sum3 << 32) & Word_HiMask);
|
||||
|
||||
lo.* = r0 +% (r1 << 64);
|
||||
hi.* = (r1 >> 64) +%
|
||||
(sum1 >> 96) +%
|
||||
(sum2 >> 64) +%
|
||||
(sum3 >> 32) +%
|
||||
sum4 +%
|
||||
(sum5 << 32) +%
|
||||
(sum6 << 64);
|
||||
},
|
||||
else => @compileError("unsupported"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T).Float.bits)) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
|
||||
const significandBits = std.math.floatMantissaBits(T);
|
||||
const implicitBit = @as(Z, 1) << significandBits;
|
||||
|
||||
const shift = @clz(Z, significand.*) - @clz(Z, implicitBit);
|
||||
significand.* <<= @intCast(std.math.Log2Int(Z), shift);
|
||||
return 1 - shift;
|
||||
}
|
||||
|
||||
pub fn __aeabi_ddiv(a: f64, b: f64) callconv(.AAPCS) f64 {
|
||||
@setRuntimeSafety(false);
|
||||
return @call(.{ .modifier = .always_inline }, __divdf3, .{ a, b });
|
||||
}
|
||||
|
||||
test {
|
||||
_ = @import("divdf3_test.zig");
|
||||
}
|
||||
@ -1,12 +1,33 @@
|
||||
// Ported from:
|
||||
//
|
||||
// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divsf3.c
|
||||
//! Ported from:
|
||||
//!
|
||||
//! https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divsf3.c
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
|
||||
const common = @import("common.zig");
|
||||
const normalize = common.normalize;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (common.want_aeabi) {
|
||||
@export(__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = common.linkage });
|
||||
} else {
|
||||
@export(__divsf3, .{ .name = "__divsf3", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return div(a, b);
|
||||
}
|
||||
|
||||
fn __aeabi_fdiv(a: f32, b: f32) callconv(.AAPCS) f32 {
|
||||
return div(a, b);
|
||||
}
|
||||
|
||||
inline fn div(a: f32, b: f32) f32 {
|
||||
const Z = std.meta.Int(.unsigned, 32);
|
||||
|
||||
const significandBits = std.math.floatMantissaBits(f32);
|
||||
@ -184,22 +205,6 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T).Float.bits)) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
|
||||
const significandBits = std.math.floatMantissaBits(T);
|
||||
const implicitBit = @as(Z, 1) << significandBits;
|
||||
|
||||
const shift = @clz(Z, significand.*) - @clz(Z, implicitBit);
|
||||
significand.* <<= @intCast(std.math.Log2Int(Z), shift);
|
||||
return 1 - shift;
|
||||
}
|
||||
|
||||
pub fn __aeabi_fdiv(a: f32, b: f32) callconv(.AAPCS) f32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @call(.{ .modifier = .always_inline }, __divsf3, .{ a, b });
|
||||
}
|
||||
|
||||
test {
|
||||
_ = @import("divsf3_test.zig");
|
||||
}
|
||||
@ -1,11 +1,35 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const normalize = @import("divdf3.zig").normalize;
|
||||
const wideMultiply = @import("divdf3.zig").wideMultiply;
|
||||
const common = @import("common.zig");
|
||||
const normalize = common.normalize;
|
||||
const wideMultiply = common.wideMultiply;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (common.want_ppc_abi) {
|
||||
@export(__divkf3, .{ .name = "__divkf3", .linkage = common.linkage });
|
||||
} else if (common.want_sparc_abi) {
|
||||
@export(_Qp_div, .{ .name = "_Qp_div", .linkage = common.linkage });
|
||||
} else {
|
||||
@export(__divtf3, .{ .name = "__divtf3", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __divtf3(a: f128, b: f128) callconv(.C) f128 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return div(a, b);
|
||||
}
|
||||
|
||||
fn __divkf3(a: f128, b: f128) callconv(.C) f128 {
|
||||
return div(a, b);
|
||||
}
|
||||
|
||||
fn _Qp_div(c: *f128, a: *const f128, b: *const f128) callconv(.C) void {
|
||||
c.* = div(a.*, b.*);
|
||||
}
|
||||
|
||||
inline fn div(a: f128, b: f128) f128 {
|
||||
const Z = std.meta.Int(.unsigned, 128);
|
||||
|
||||
const significandBits = std.math.floatMantissaBits(f128);
|
||||
@ -34,8 +34,12 @@ test "divtf3" {
|
||||
try test__divtf3(math.qnan_f128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0);
|
||||
// NaN / any = NaN
|
||||
try test__divtf3(math.nan_f128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0);
|
||||
// inf / any = inf
|
||||
try test__divtf3(math.inf_f128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0);
|
||||
// inf / any(except inf and nan) = inf
|
||||
try test__divtf3(math.inf(f128), 0x1.23456789abcdefp+5, 0x7fff000000000000, 0);
|
||||
// inf / inf = nan
|
||||
try test__divtf3(math.inf(f128), math.inf(f128), 0x7fff800000000000, 0);
|
||||
// inf / nan = nan
|
||||
try test__divtf3(math.inf(f128), math.nan(f128), 0x7fff800000000000, 0);
|
||||
|
||||
try test__divtf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.eedcbaba3a94546558237654321fp-1, 0x4004b0b72924d407, 0x0717e84356c6eba2);
|
||||
try test__divtf3(0x1.a2b34c56d745382f9abf2c3dfeffp-50, 0x1.ed2c3ba15935332532287654321fp-9, 0x3fd5b2af3f828c9b, 0x40e51f64cde8b1f2);
|
||||
54
lib/compiler_rt/divti3.zig
Normal file
54
lib/compiler_rt/divti3.zig
Normal file
@ -0,0 +1,54 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const udivmod = @import("udivmod.zig").udivmod;
|
||||
const arch = builtin.cpu.arch;
|
||||
const common = @import("common.zig");
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (builtin.os.tag == .windows) {
|
||||
switch (arch) {
|
||||
.i386 => {
|
||||
@export(__divti3, .{ .name = "__divti3", .linkage = common.linkage });
|
||||
},
|
||||
.x86_64 => {
|
||||
// The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI
|
||||
// that LLVM expects compiler-rt to have.
|
||||
@export(__divti3_windows_x86_64, .{ .name = "__divti3", .linkage = common.linkage });
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
if (arch.isAARCH64()) {
|
||||
@export(__divti3, .{ .name = "__divti3", .linkage = common.linkage });
|
||||
}
|
||||
} else {
|
||||
@export(__divti3, .{ .name = "__divti3", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __divti3(a: i128, b: i128) callconv(.C) i128 {
|
||||
return div(a, b);
|
||||
}
|
||||
|
||||
const v128 = @import("std").meta.Vector(2, u64);
|
||||
|
||||
fn __divti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 {
|
||||
return @bitCast(v128, div(@bitCast(i128, a), @bitCast(i128, b)));
|
||||
}
|
||||
|
||||
inline fn div(a: i128, b: i128) i128 {
|
||||
const s_a = a >> (128 - 1);
|
||||
const s_b = b >> (128 - 1);
|
||||
|
||||
const an = (a ^ s_a) -% s_a;
|
||||
const bn = (b ^ s_b) -% s_b;
|
||||
|
||||
const r = udivmod(u128, @bitCast(u128, an), @bitCast(u128, bn), null);
|
||||
const s = s_a ^ s_b;
|
||||
return (@bitCast(i128, r) ^ s) -% s;
|
||||
}
|
||||
|
||||
test {
|
||||
_ = @import("divti3_test.zig");
|
||||
}
|
||||
210
lib/compiler_rt/divxf3.zig
Normal file
210
lib/compiler_rt/divxf3.zig
Normal file
@ -0,0 +1,210 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
|
||||
const common = @import("common.zig");
|
||||
const normalize = common.normalize;
|
||||
const wideMultiply = common.wideMultiply;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__divxf3, .{ .name = "__divxf3", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
pub fn __divxf3(a: f80, b: f80) callconv(.C) f80 {
|
||||
const T = f80;
|
||||
const Z = std.meta.Int(.unsigned, @bitSizeOf(T));
|
||||
|
||||
const significandBits = std.math.floatMantissaBits(T);
|
||||
const fractionalBits = std.math.floatFractionalBits(T);
|
||||
const exponentBits = std.math.floatExponentBits(T);
|
||||
|
||||
const signBit = (@as(Z, 1) << (significandBits + exponentBits));
|
||||
const maxExponent = ((1 << exponentBits) - 1);
|
||||
const exponentBias = (maxExponent >> 1);
|
||||
|
||||
const integerBit = (@as(Z, 1) << fractionalBits);
|
||||
const quietBit = integerBit >> 1;
|
||||
const significandMask = (@as(Z, 1) << significandBits) - 1;
|
||||
|
||||
const absMask = signBit - 1;
|
||||
const qnanRep = @bitCast(Z, std.math.nan(T)) | quietBit;
|
||||
const infRep = @bitCast(Z, std.math.inf(T));
|
||||
|
||||
const aExponent = @truncate(u32, (@bitCast(Z, a) >> significandBits) & maxExponent);
|
||||
const bExponent = @truncate(u32, (@bitCast(Z, b) >> significandBits) & maxExponent);
|
||||
const quotientSign: Z = (@bitCast(Z, a) ^ @bitCast(Z, b)) & signBit;
|
||||
|
||||
var aSignificand: Z = @bitCast(Z, a) & significandMask;
|
||||
var bSignificand: Z = @bitCast(Z, b) & significandMask;
|
||||
var scale: i32 = 0;
|
||||
|
||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
||||
if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
|
||||
const aAbs: Z = @bitCast(Z, a) & absMask;
|
||||
const bAbs: Z = @bitCast(Z, b) & absMask;
|
||||
|
||||
// NaN / anything = qNaN
|
||||
if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit);
|
||||
// anything / NaN = qNaN
|
||||
if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit);
|
||||
|
||||
if (aAbs == infRep) {
|
||||
// infinity / infinity = NaN
|
||||
if (bAbs == infRep) {
|
||||
return @bitCast(T, qnanRep);
|
||||
}
|
||||
// infinity / anything else = +/- infinity
|
||||
else {
|
||||
return @bitCast(T, aAbs | quotientSign);
|
||||
}
|
||||
}
|
||||
|
||||
// anything else / infinity = +/- 0
|
||||
if (bAbs == infRep) return @bitCast(T, quotientSign);
|
||||
|
||||
if (aAbs == 0) {
|
||||
// zero / zero = NaN
|
||||
if (bAbs == 0) {
|
||||
return @bitCast(T, qnanRep);
|
||||
}
|
||||
// zero / anything else = +/- zero
|
||||
else {
|
||||
return @bitCast(T, quotientSign);
|
||||
}
|
||||
}
|
||||
// anything else / zero = +/- infinity
|
||||
if (bAbs == 0) return @bitCast(T, infRep | quotientSign);
|
||||
|
||||
// one or both of a or b is denormal, the other (if applicable) is a
|
||||
// normal number. Renormalize one or both of a and b, and set scale to
|
||||
// include the necessary exponent adjustment.
|
||||
if (aAbs < integerBit) scale +%= normalize(T, &aSignificand);
|
||||
if (bAbs < integerBit) scale -%= normalize(T, &bSignificand);
|
||||
}
|
||||
var quotientExponent: i32 = @bitCast(i32, aExponent -% bExponent) +% scale;
|
||||
|
||||
// Align the significand of b as a Q63 fixed-point number in the range
|
||||
// [1, 2.0) and get a Q64 approximate reciprocal using a small minimax
|
||||
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
|
||||
// is accurate to about 3.5 binary digits.
|
||||
const q63b = @intCast(u64, bSignificand);
|
||||
var recip64 = @as(u64, 0x7504f333F9DE6484) -% q63b;
|
||||
// 0x7504f333F9DE6484 / 2^64 + 1 = 3/4 + 1/sqrt(2)
|
||||
|
||||
// Now refine the reciprocal estimate using a Newton-Raphson iteration:
|
||||
//
|
||||
// x1 = x0 * (2 - x0 * b)
|
||||
//
|
||||
// This doubles the number of correct binary digits in the approximation
|
||||
// with each iteration.
|
||||
var correction64: u64 = undefined;
|
||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
||||
correction64 = @truncate(u64, ~(@as(u128, recip64) *% q63b >> 64) +% 1);
|
||||
recip64 = @truncate(u64, @as(u128, recip64) *% correction64 >> 63);
|
||||
|
||||
// The reciprocal may have overflowed to zero if the upper half of b is
|
||||
// exactly 1.0. This would sabatoge the full-width final stage of the
|
||||
// computation that follows, so we adjust the reciprocal down by one bit.
|
||||
recip64 -%= 1;
|
||||
|
||||
// We need to perform one more iteration to get us to 112 binary digits;
|
||||
// The last iteration needs to happen with extra precision.
|
||||
|
||||
// NOTE: This operation is equivalent to __multi3, which is not implemented
|
||||
// in some architechures
|
||||
var reciprocal: u128 = undefined;
|
||||
var correction: u128 = undefined;
|
||||
var dummy: u128 = undefined;
|
||||
wideMultiply(u128, recip64, q63b, &dummy, &correction);
|
||||
|
||||
correction = -%correction;
|
||||
|
||||
const cHi = @truncate(u64, correction >> 64);
|
||||
const cLo = @truncate(u64, correction);
|
||||
|
||||
var r64cH: u128 = undefined;
|
||||
var r64cL: u128 = undefined;
|
||||
wideMultiply(u128, recip64, cHi, &dummy, &r64cH);
|
||||
wideMultiply(u128, recip64, cLo, &dummy, &r64cL);
|
||||
|
||||
reciprocal = r64cH + (r64cL >> 64);
|
||||
|
||||
// Adjust the final 128-bit reciprocal estimate downward to ensure that it
|
||||
// is strictly smaller than the infinitely precise exact reciprocal. Because
|
||||
// the computation of the Newton-Raphson step is truncating at every step,
|
||||
// this adjustment is small; most of the work is already done.
|
||||
reciprocal -%= 2;
|
||||
|
||||
// The numerical reciprocal is accurate to within 2^-112, lies in the
|
||||
// interval [0.5, 1.0), and is strictly smaller than the true reciprocal
|
||||
// of b. Multiplying a by this reciprocal thus gives a numerical q = a/b
|
||||
// in Q127 with the following properties:
|
||||
//
|
||||
// 1. q < a/b
|
||||
// 2. q is in the interval [0.5, 2.0)
|
||||
// 3. The error in q is bounded away from 2^-63 (actually, we have
|
||||
// many bits to spare, but this is all we need).
|
||||
|
||||
// We need a 128 x 128 multiply high to compute q.
|
||||
var quotient128: u128 = undefined;
|
||||
var quotientLo: u128 = undefined;
|
||||
wideMultiply(u128, aSignificand << 2, reciprocal, "ient128, "ientLo);
|
||||
|
||||
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
|
||||
// Right shift the quotient if it falls in the [1,2) range and adjust the
|
||||
// exponent accordingly.
|
||||
var quotient: u64 = if (quotient128 < (integerBit << 1)) b: {
|
||||
quotientExponent -= 1;
|
||||
break :b @intCast(u64, quotient128);
|
||||
} else @intCast(u64, quotient128 >> 1);
|
||||
|
||||
// We are going to compute a residual of the form
|
||||
//
|
||||
// r = a - q*b
|
||||
//
|
||||
// We know from the construction of q that r satisfies:
|
||||
//
|
||||
// 0 <= r < ulp(q)*b
|
||||
//
|
||||
// If r is greater than 1/2 ulp(q)*b, then q rounds up. Otherwise, we
|
||||
// already have the correct result. The exact halfway case cannot occur.
|
||||
var residual: u64 = -%(quotient *% q63b);
|
||||
|
||||
const writtenExponent = quotientExponent + exponentBias;
|
||||
if (writtenExponent >= maxExponent) {
|
||||
// If we have overflowed the exponent, return infinity.
|
||||
return @bitCast(T, infRep | quotientSign);
|
||||
} else if (writtenExponent < 1) {
|
||||
if (writtenExponent == 0) {
|
||||
// Check whether the rounded result is normal.
|
||||
if (residual > (bSignificand >> 1)) { // round
|
||||
if (quotient == (integerBit - 1)) // If the rounded result is normal, return it
|
||||
return @bitCast(T, @bitCast(Z, std.math.floatMin(T)) | quotientSign);
|
||||
}
|
||||
}
|
||||
// Flush denormals to zero. In the future, it would be nice to add
|
||||
// code to round them correctly.
|
||||
return @bitCast(T, quotientSign);
|
||||
} else {
|
||||
const round = @boolToInt(residual > (bSignificand >> 1));
|
||||
// Insert the exponent
|
||||
var absResult = quotient | (@intCast(Z, writtenExponent) << significandBits);
|
||||
// Round
|
||||
absResult +%= round;
|
||||
// Insert the sign and return
|
||||
return @bitCast(T, absResult | quotientSign | integerBit);
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
_ = @import("divxf3_test.zig");
|
||||
}
|
||||
65
lib/compiler_rt/divxf3_test.zig
Normal file
65
lib/compiler_rt/divxf3_test.zig
Normal file
@ -0,0 +1,65 @@
|
||||
const std = @import("std");
|
||||
const math = std.math;
|
||||
const testing = std.testing;
|
||||
|
||||
const __divxf3 = @import("divxf3.zig").__divxf3;
|
||||
|
||||
fn compareResult(result: f80, expected: u80) bool {
|
||||
const rep = @bitCast(u80, result);
|
||||
|
||||
if (rep == expected) return true;
|
||||
// test other possible NaN representations (signal NaN)
|
||||
if (math.isNan(result) and math.isNan(@bitCast(f80, expected))) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
fn expect__divxf3_result(a: f80, b: f80, expected: u80) !void {
|
||||
const x = __divxf3(a, b);
|
||||
const ret = compareResult(x, expected);
|
||||
try testing.expect(ret == true);
|
||||
}
|
||||
|
||||
fn test__divxf3(a: f80, b: f80) !void {
|
||||
const integerBit = 1 << math.floatFractionalBits(f80);
|
||||
const x = __divxf3(a, b);
|
||||
|
||||
// Next float (assuming normal, non-zero result)
|
||||
const x_plus_eps = @bitCast(f80, (@bitCast(u80, x) + 1) | integerBit);
|
||||
// Prev float (assuming normal, non-zero result)
|
||||
const x_minus_eps = @bitCast(f80, (@bitCast(u80, x) - 1) | integerBit);
|
||||
|
||||
// Make sure result is more accurate than the adjacent floats
|
||||
const err_x = @fabs(@mulAdd(f80, x, b, -a));
|
||||
const err_x_plus_eps = @fabs(@mulAdd(f80, x_plus_eps, b, -a));
|
||||
const err_x_minus_eps = @fabs(@mulAdd(f80, x_minus_eps, b, -a));
|
||||
|
||||
try testing.expect(err_x_minus_eps > err_x);
|
||||
try testing.expect(err_x_plus_eps > err_x);
|
||||
}
|
||||
|
||||
test "divxf3" {
|
||||
// qNaN / any = qNaN
|
||||
try expect__divxf3_result(math.qnan_f80, 0x1.23456789abcdefp+5, 0x7fffC000000000000000);
|
||||
// NaN / any = NaN
|
||||
try expect__divxf3_result(math.nan_f80, 0x1.23456789abcdefp+5, 0x7fffC000000000000000);
|
||||
// inf / any(except inf and nan) = inf
|
||||
try expect__divxf3_result(math.inf(f80), 0x1.23456789abcdefp+5, 0x7fff8000000000000000);
|
||||
// inf / inf = nan
|
||||
try expect__divxf3_result(math.inf(f80), math.inf(f80), 0x7fffC000000000000000);
|
||||
// inf / nan = nan
|
||||
try expect__divxf3_result(math.inf(f80), math.nan(f80), 0x7fffC000000000000000);
|
||||
|
||||
try test__divxf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.eedcbaba3a94546558237654321fp-1);
|
||||
try test__divxf3(0x1.a2b34c56d745382f9abf2c3dfeffp-50, 0x1.ed2c3ba15935332532287654321fp-9);
|
||||
try test__divxf3(0x1.2345f6aaaa786555f42432abcdefp+456, 0x1.edacbba9874f765463544dd3621fp+6400);
|
||||
try test__divxf3(0x1.2d3456f789ba6322bc665544edefp-234, 0x1.eddcdba39f3c8b7a36564354321fp-4455);
|
||||
try test__divxf3(0x1.2345f6b77b7a8953365433abcdefp+234, 0x1.edcba987d6bb3aa467754354321fp-4055);
|
||||
try test__divxf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.a2b34c56d745382f9abf2c3dfeffp-50);
|
||||
try test__divxf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.1234567890abcdef987654321123p0);
|
||||
try test__divxf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.12394205810257120adae8929f23p+16);
|
||||
try test__divxf3(0x1.a23b45362464523375893ab4cdefp+5, 0x1.febdcefa1231245f9abf2c3dfeffp-50);
|
||||
|
||||
// Result rounds down to zero
|
||||
try expect__divxf3_result(6.72420628622418701252535563464350521E-4932, 2.0, 0x0);
|
||||
}
|
||||
@ -1,22 +1,26 @@
|
||||
// __emutls_get_address specific builtin
|
||||
//
|
||||
// derived work from LLVM Compiler Infrastructure - release 8.0 (MIT)
|
||||
// https://github.com/llvm-mirror/compiler-rt/blob/release_80/lib/builtins/emutls.c
|
||||
//
|
||||
//! __emutls_get_address specific builtin
|
||||
//!
|
||||
//! derived work from LLVM Compiler Infrastructure - release 8.0 (MIT)
|
||||
//! https://github.com/llvm-mirror/compiler-rt/blob/release_80/lib/builtins/emutls.c
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const common = @import("common.zig");
|
||||
|
||||
const abort = std.os.abort;
|
||||
const assert = std.debug.assert;
|
||||
const expect = std.testing.expect;
|
||||
|
||||
// defined in C as:
|
||||
// typedef unsigned int gcc_word __attribute__((mode(word)));
|
||||
/// defined in C as:
|
||||
/// typedef unsigned int gcc_word __attribute__((mode(word)));
|
||||
const gcc_word = usize;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
assert(builtin.link_libc);
|
||||
if (builtin.link_libc and builtin.os.tag == .openbsd) {
|
||||
@export(__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
/// public entrypoint for generated code using EmulatedTLS
|
||||
@ -319,6 +323,8 @@ const emutls_control = extern struct {
|
||||
};
|
||||
|
||||
test "simple_allocator" {
|
||||
if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest;
|
||||
|
||||
var data1: *[64]u8 = simple_allocator.alloc([64]u8);
|
||||
defer simple_allocator.free(data1);
|
||||
for (data1) |*c| {
|
||||
@ -333,6 +339,8 @@ test "simple_allocator" {
|
||||
}
|
||||
|
||||
test "__emutls_get_address zeroed" {
|
||||
if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest;
|
||||
|
||||
var ctl = emutls_control.init(usize, null);
|
||||
try expect(ctl.object.index == 0);
|
||||
|
||||
@ -352,6 +360,8 @@ test "__emutls_get_address zeroed" {
|
||||
}
|
||||
|
||||
test "__emutls_get_address with default_value" {
|
||||
if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest;
|
||||
|
||||
var value: usize = 5678; // default value
|
||||
var ctl = emutls_control.init(usize, &value);
|
||||
try expect(ctl.object.index == 0);
|
||||
@ -370,6 +380,8 @@ test "__emutls_get_address with default_value" {
|
||||
}
|
||||
|
||||
test "test default_value with differents sizes" {
|
||||
if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest;
|
||||
|
||||
const testType = struct {
|
||||
fn _testType(comptime T: type, value: T) !void {
|
||||
var def: T = value;
|
||||
@ -4,25 +4,31 @@
|
||||
// https://git.musl-libc.org/cgit/musl/tree/src/math/expf.c
|
||||
// https://git.musl-libc.org/cgit/musl/tree/src/math/exp.c
|
||||
|
||||
const std = @import("../std.zig");
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
const math = std.math;
|
||||
const expect = std.testing.expect;
|
||||
const common = @import("common.zig");
|
||||
|
||||
/// Returns e raised to the power of x (e^x).
|
||||
///
|
||||
/// Special Cases:
|
||||
/// - exp(+inf) = +inf
|
||||
/// - exp(nan) = nan
|
||||
pub fn exp(x: anytype) @TypeOf(x) {
|
||||
const T = @TypeOf(x);
|
||||
return switch (T) {
|
||||
f32 => exp32(x),
|
||||
f64 => exp64(x),
|
||||
else => @compileError("exp not implemented for " ++ @typeName(T)),
|
||||
};
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__exph, .{ .name = "__exph", .linkage = common.linkage });
|
||||
@export(expf, .{ .name = "expf", .linkage = common.linkage });
|
||||
@export(exp, .{ .name = "exp", .linkage = common.linkage });
|
||||
@export(__expx, .{ .name = "__expx", .linkage = common.linkage });
|
||||
const expq_sym_name = if (common.want_ppc_abi) "expf128" else "expq";
|
||||
@export(expq, .{ .name = expq_sym_name, .linkage = common.linkage });
|
||||
@export(expl, .{ .name = "expl", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
fn exp32(x_: f32) f32 {
|
||||
pub fn __exph(a: f16) callconv(.C) f16 {
|
||||
// TODO: more efficient implementation
|
||||
return @floatCast(f16, expf(a));
|
||||
}
|
||||
|
||||
pub fn expf(x_: f32) callconv(.C) f32 {
|
||||
const half = [_]f32{ 0.5, -0.5 };
|
||||
const ln2hi = 6.9314575195e-1;
|
||||
const ln2lo = 1.4286067653e-6;
|
||||
@ -97,7 +103,7 @@ fn exp32(x_: f32) f32 {
|
||||
}
|
||||
}
|
||||
|
||||
fn exp64(x_: f64) f64 {
|
||||
pub fn exp(x_: f64) callconv(.C) f64 {
|
||||
const half = [_]f64{ 0.5, -0.5 };
|
||||
const ln2hi: f64 = 6.93147180369123816490e-01;
|
||||
const ln2lo: f64 = 1.90821492927058770002e-10;
|
||||
@ -181,37 +187,53 @@ fn exp64(x_: f64) f64 {
|
||||
}
|
||||
}
|
||||
|
||||
test "math.exp" {
|
||||
try expect(exp(@as(f32, 0.0)) == exp32(0.0));
|
||||
try expect(exp(@as(f64, 0.0)) == exp64(0.0));
|
||||
pub fn __expx(a: f80) callconv(.C) f80 {
|
||||
// TODO: more efficient implementation
|
||||
return @floatCast(f80, expq(a));
|
||||
}
|
||||
|
||||
test "math.exp32" {
|
||||
pub fn expq(a: f128) callconv(.C) f128 {
|
||||
// TODO: more correct implementation
|
||||
return exp(@floatCast(f64, a));
|
||||
}
|
||||
|
||||
pub fn expl(x: c_longdouble) callconv(.C) c_longdouble {
|
||||
switch (@typeInfo(c_longdouble).Float.bits) {
|
||||
16 => return __exph(x),
|
||||
32 => return expf(x),
|
||||
64 => return exp(x),
|
||||
80 => return __expx(x),
|
||||
128 => return expq(x),
|
||||
else => @compileError("unreachable"),
|
||||
}
|
||||
}
|
||||
|
||||
test "exp32" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(exp32(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f32, exp32(0.0), 1.0, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp32(0.2), 1.221403, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp32(0.8923), 2.440737, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp32(1.5), 4.481689, epsilon));
|
||||
try expect(expf(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f32, expf(0.0), 1.0, epsilon));
|
||||
try expect(math.approxEqAbs(f32, expf(0.2), 1.221403, epsilon));
|
||||
try expect(math.approxEqAbs(f32, expf(0.8923), 2.440737, epsilon));
|
||||
try expect(math.approxEqAbs(f32, expf(1.5), 4.481689, epsilon));
|
||||
}
|
||||
|
||||
test "math.exp64" {
|
||||
test "exp64" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(exp64(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f64, exp64(0.0), 1.0, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp64(0.2), 1.221403, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp64(0.8923), 2.440737, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp64(1.5), 4.481689, epsilon));
|
||||
try expect(exp(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f64, exp(0.0), 1.0, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp(0.2), 1.221403, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp(0.8923), 2.440737, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp(1.5), 4.481689, epsilon));
|
||||
}
|
||||
|
||||
test "math.exp32.special" {
|
||||
try expect(math.isPositiveInf(exp32(math.inf(f32))));
|
||||
try expect(math.isNan(exp32(math.nan(f32))));
|
||||
test "exp32.special" {
|
||||
try expect(math.isPositiveInf(expf(math.inf(f32))));
|
||||
try expect(math.isNan(expf(math.nan(f32))));
|
||||
}
|
||||
|
||||
test "math.exp64.special" {
|
||||
try expect(math.isPositiveInf(exp64(math.inf(f64))));
|
||||
try expect(math.isNan(exp64(math.nan(f64))));
|
||||
test "exp64.special" {
|
||||
try expect(math.isPositiveInf(exp(math.inf(f64))));
|
||||
try expect(math.isNan(exp(math.nan(f64))));
|
||||
}
|
||||
@ -4,44 +4,31 @@
|
||||
// https://git.musl-libc.org/cgit/musl/tree/src/math/exp2f.c
|
||||
// https://git.musl-libc.org/cgit/musl/tree/src/math/exp2.c
|
||||
|
||||
const std = @import("../std.zig");
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const arch = builtin.cpu.arch;
|
||||
const math = std.math;
|
||||
const expect = std.testing.expect;
|
||||
const common = @import("common.zig");
|
||||
|
||||
/// Returns 2 raised to the power of x (2^x).
|
||||
///
|
||||
/// Special Cases:
|
||||
/// - exp2(+inf) = +inf
|
||||
/// - exp2(nan) = nan
|
||||
pub fn exp2(x: anytype) @TypeOf(x) {
|
||||
const T = @TypeOf(x);
|
||||
return switch (T) {
|
||||
f32 => exp2_32(x),
|
||||
f64 => exp2_64(x),
|
||||
else => @compileError("exp2 not implemented for " ++ @typeName(T)),
|
||||
};
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
@export(__exp2h, .{ .name = "__exp2h", .linkage = common.linkage });
|
||||
@export(exp2f, .{ .name = "exp2f", .linkage = common.linkage });
|
||||
@export(exp2, .{ .name = "exp2", .linkage = common.linkage });
|
||||
@export(__exp2x, .{ .name = "__exp2x", .linkage = common.linkage });
|
||||
const exp2q_sym_name = if (common.want_ppc_abi) "exp2f128" else "exp2q";
|
||||
@export(exp2q, .{ .name = exp2q_sym_name, .linkage = common.linkage });
|
||||
@export(exp2l, .{ .name = "exp2l", .linkage = common.linkage });
|
||||
}
|
||||
|
||||
const exp2ft = [_]f64{
|
||||
0x1.6a09e667f3bcdp-1,
|
||||
0x1.7a11473eb0187p-1,
|
||||
0x1.8ace5422aa0dbp-1,
|
||||
0x1.9c49182a3f090p-1,
|
||||
0x1.ae89f995ad3adp-1,
|
||||
0x1.c199bdd85529cp-1,
|
||||
0x1.d5818dcfba487p-1,
|
||||
0x1.ea4afa2a490dap-1,
|
||||
0x1.0000000000000p+0,
|
||||
0x1.0b5586cf9890fp+0,
|
||||
0x1.172b83c7d517bp+0,
|
||||
0x1.2387a6e756238p+0,
|
||||
0x1.306fe0a31b715p+0,
|
||||
0x1.3dea64c123422p+0,
|
||||
0x1.4bfdad5362a27p+0,
|
||||
0x1.5ab07dd485429p+0,
|
||||
};
|
||||
pub fn __exp2h(x: f16) callconv(.C) f16 {
|
||||
// TODO: more efficient implementation
|
||||
return @floatCast(f16, exp2f(x));
|
||||
}
|
||||
|
||||
fn exp2_32(x: f32) f32 {
|
||||
pub fn exp2f(x: f32) callconv(.C) f32 {
|
||||
const tblsiz = @intCast(u32, exp2ft.len);
|
||||
const redux: f32 = 0x1.8p23 / @intToFloat(f32, tblsiz);
|
||||
const P1: f32 = 0x1.62e430p-1;
|
||||
@ -98,6 +85,115 @@ fn exp2_32(x: f32) f32 {
|
||||
return @floatCast(f32, r * uk);
|
||||
}
|
||||
|
||||
pub fn exp2(x: f64) callconv(.C) f64 {
|
||||
const tblsiz: u32 = @intCast(u32, exp2dt.len / 2);
|
||||
const redux: f64 = 0x1.8p52 / @intToFloat(f64, tblsiz);
|
||||
const P1: f64 = 0x1.62e42fefa39efp-1;
|
||||
const P2: f64 = 0x1.ebfbdff82c575p-3;
|
||||
const P3: f64 = 0x1.c6b08d704a0a6p-5;
|
||||
const P4: f64 = 0x1.3b2ab88f70400p-7;
|
||||
const P5: f64 = 0x1.5d88003875c74p-10;
|
||||
|
||||
const ux = @bitCast(u64, x);
|
||||
const ix = @intCast(u32, ux >> 32) & 0x7FFFFFFF;
|
||||
|
||||
// TODO: This should be handled beneath.
|
||||
if (math.isNan(x)) {
|
||||
return math.nan(f64);
|
||||
}
|
||||
|
||||
// |x| >= 1022 or nan
|
||||
if (ix >= 0x408FF000) {
|
||||
// x >= 1024 or nan
|
||||
if (ix >= 0x40900000 and ux >> 63 == 0) {
|
||||
math.raiseOverflow();
|
||||
return math.inf(f64);
|
||||
}
|
||||
// -inf or -nan
|
||||
if (ix >= 0x7FF00000) {
|
||||
return -1 / x;
|
||||
}
|
||||
// x <= -1022
|
||||
if (ux >> 63 != 0) {
|
||||
// underflow
|
||||
if (x <= -1075 or x - 0x1.0p52 + 0x1.0p52 != x) {
|
||||
math.doNotOptimizeAway(@floatCast(f32, -0x1.0p-149 / x));
|
||||
}
|
||||
if (x <= -1075) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// |x| < 0x1p-54
|
||||
else if (ix < 0x3C900000) {
|
||||
return 1.0 + x;
|
||||
}
|
||||
|
||||
// NOTE: musl relies on unsafe behaviours which are replicated below
|
||||
// (addition overflow, division truncation, casting). Appears that this
|
||||
// produces the intended result but should confirm how GCC/Clang handle this
|
||||
// to ensure.
|
||||
|
||||
// reduce x
|
||||
var uf: f64 = x + redux;
|
||||
// NOTE: musl performs an implicit 64-bit to 32-bit u32 truncation here
|
||||
var i_0: u32 = @truncate(u32, @bitCast(u64, uf));
|
||||
i_0 +%= tblsiz / 2;
|
||||
|
||||
const k: u32 = i_0 / tblsiz * tblsiz;
|
||||
const ik: i32 = @divTrunc(@bitCast(i32, k), tblsiz);
|
||||
i_0 %= tblsiz;
|
||||
uf -= redux;
|
||||
|
||||
// r = exp2(y) = exp2t[i_0] * p(z - eps[i])
|
||||
var z: f64 = x - uf;
|
||||
const t: f64 = exp2dt[@intCast(usize, 2 * i_0)];
|
||||
z -= exp2dt[@intCast(usize, 2 * i_0 + 1)];
|
||||
const r: f64 = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5))));
|
||||
|
||||
return math.scalbn(r, ik);
|
||||
}
|
||||
|
||||
pub fn __exp2x(x: f80) callconv(.C) f80 {
|
||||
// TODO: more efficient implementation
|
||||
return @floatCast(f80, exp2q(x));
|
||||
}
|
||||
|
||||
pub fn exp2q(x: f128) callconv(.C) f128 {
|
||||
// TODO: more correct implementation
|
||||
return exp2(@floatCast(f64, x));
|
||||
}
|
||||
|
||||
pub fn exp2l(x: c_longdouble) callconv(.C) c_longdouble {
|
||||
switch (@typeInfo(c_longdouble).Float.bits) {
|
||||
16 => return __exp2h(x),
|
||||
32 => return exp2f(x),
|
||||
64 => return exp2(x),
|
||||
80 => return __exp2x(x),
|
||||
128 => return exp2q(x),
|
||||
else => @compileError("unreachable"),
|
||||
}
|
||||
}
|
||||
|
||||
const exp2ft = [_]f64{
|
||||
0x1.6a09e667f3bcdp-1,
|
||||
0x1.7a11473eb0187p-1,
|
||||
0x1.8ace5422aa0dbp-1,
|
||||
0x1.9c49182a3f090p-1,
|
||||
0x1.ae89f995ad3adp-1,
|
||||
0x1.c199bdd85529cp-1,
|
||||
0x1.d5818dcfba487p-1,
|
||||
0x1.ea4afa2a490dap-1,
|
||||
0x1.0000000000000p+0,
|
||||
0x1.0b5586cf9890fp+0,
|
||||
0x1.172b83c7d517bp+0,
|
||||
0x1.2387a6e756238p+0,
|
||||
0x1.306fe0a31b715p+0,
|
||||
0x1.3dea64c123422p+0,
|
||||
0x1.4bfdad5362a27p+0,
|
||||
0x1.5ab07dd485429p+0,
|
||||
};
|
||||
|
||||
const exp2dt = [_]f64{
|
||||
// exp2(z + eps) eps
|
||||
0x1.6a09e667f3d5dp-1, 0x1.9880p-44,
|
||||
@ -358,108 +454,34 @@ const exp2dt = [_]f64{
|
||||
0x1.690f4b19e9471p+0, -0x1.9780p-45,
|
||||
};
|
||||
|
||||
fn exp2_64(x: f64) f64 {
|
||||
const tblsiz: u32 = @intCast(u32, exp2dt.len / 2);
|
||||
const redux: f64 = 0x1.8p52 / @intToFloat(f64, tblsiz);
|
||||
const P1: f64 = 0x1.62e42fefa39efp-1;
|
||||
const P2: f64 = 0x1.ebfbdff82c575p-3;
|
||||
const P3: f64 = 0x1.c6b08d704a0a6p-5;
|
||||
const P4: f64 = 0x1.3b2ab88f70400p-7;
|
||||
const P5: f64 = 0x1.5d88003875c74p-10;
|
||||
|
||||
const ux = @bitCast(u64, x);
|
||||
const ix = @intCast(u32, ux >> 32) & 0x7FFFFFFF;
|
||||
|
||||
// TODO: This should be handled beneath.
|
||||
if (math.isNan(x)) {
|
||||
return math.nan(f64);
|
||||
}
|
||||
|
||||
// |x| >= 1022 or nan
|
||||
if (ix >= 0x408FF000) {
|
||||
// x >= 1024 or nan
|
||||
if (ix >= 0x40900000 and ux >> 63 == 0) {
|
||||
math.raiseOverflow();
|
||||
return math.inf(f64);
|
||||
}
|
||||
// -inf or -nan
|
||||
if (ix >= 0x7FF00000) {
|
||||
return -1 / x;
|
||||
}
|
||||
// x <= -1022
|
||||
if (ux >> 63 != 0) {
|
||||
// underflow
|
||||
if (x <= -1075 or x - 0x1.0p52 + 0x1.0p52 != x) {
|
||||
math.doNotOptimizeAway(@floatCast(f32, -0x1.0p-149 / x));
|
||||
}
|
||||
if (x <= -1075) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// |x| < 0x1p-54
|
||||
else if (ix < 0x3C900000) {
|
||||
return 1.0 + x;
|
||||
}
|
||||
|
||||
// NOTE: musl relies on unsafe behaviours which are replicated below
|
||||
// (addition overflow, division truncation, casting). Appears that this
|
||||
// produces the intended result but should confirm how GCC/Clang handle this
|
||||
// to ensure.
|
||||
|
||||
// reduce x
|
||||
var uf: f64 = x + redux;
|
||||
// NOTE: musl performs an implicit 64-bit to 32-bit u32 truncation here
|
||||
var i_0: u32 = @truncate(u32, @bitCast(u64, uf));
|
||||
i_0 +%= tblsiz / 2;
|
||||
|
||||
const k: u32 = i_0 / tblsiz * tblsiz;
|
||||
const ik: i32 = @divTrunc(@bitCast(i32, k), tblsiz);
|
||||
i_0 %= tblsiz;
|
||||
uf -= redux;
|
||||
|
||||
// r = exp2(y) = exp2t[i_0] * p(z - eps[i])
|
||||
var z: f64 = x - uf;
|
||||
const t: f64 = exp2dt[@intCast(usize, 2 * i_0)];
|
||||
z -= exp2dt[@intCast(usize, 2 * i_0 + 1)];
|
||||
const r: f64 = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5))));
|
||||
|
||||
return math.scalbn(r, ik);
|
||||
}
|
||||
|
||||
test "math.exp2" {
|
||||
try expect(exp2(@as(f32, 0.8923)) == exp2_32(0.8923));
|
||||
try expect(exp2(@as(f64, 0.8923)) == exp2_64(0.8923));
|
||||
}
|
||||
|
||||
test "math.exp2_32" {
|
||||
test "exp2_32" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(exp2_32(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f32, exp2_32(0.2), 1.148698, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2_32(0.8923), 1.856133, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2_32(1.5), 2.828427, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2_32(37.45), 187747237888, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2_32(-1), 0.5, epsilon));
|
||||
try expect(exp2f(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f32, exp2f(0.2), 1.148698, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2f(0.8923), 1.856133, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2f(1.5), 2.828427, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2f(37.45), 187747237888, epsilon));
|
||||
try expect(math.approxEqAbs(f32, exp2f(-1), 0.5, epsilon));
|
||||
}
|
||||
|
||||
test "math.exp2_64" {
|
||||
test "exp2_64" {
|
||||
const epsilon = 0.000001;
|
||||
|
||||
try expect(exp2_64(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f64, exp2_64(0.2), 1.148698, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2_64(0.8923), 1.856133, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2_64(1.5), 2.828427, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2_64(-1), 0.5, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2_64(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1, epsilon));
|
||||
try expect(exp2(0.0) == 1.0);
|
||||
try expect(math.approxEqAbs(f64, exp2(0.2), 1.148698, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2(0.8923), 1.856133, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2(1.5), 2.828427, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2(-1), 0.5, epsilon));
|
||||
try expect(math.approxEqAbs(f64, exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1, epsilon));
|
||||
}
|
||||
|
||||
test "math.exp2_32.special" {
|
||||
try expect(math.isPositiveInf(exp2_32(math.inf(f32))));
|
||||
try expect(math.isNan(exp2_32(math.nan(f32))));
|
||||
test "exp2_32.special" {
|
||||
try expect(math.isPositiveInf(exp2f(math.inf(f32))));
|
||||
try expect(math.isNan(exp2f(math.nan(f32))));
|
||||
}
|
||||
|
||||
test "math.exp2_64.special" {
|
||||
try expect(math.isPositiveInf(exp2_64(math.inf(f64))));
|
||||
try expect(math.isNan(exp2_64(math.nan(f64))));
|
||||
test "exp2_64.special" {
|
||||
try expect(math.isPositiveInf(exp2(math.inf(f64))));
|
||||
try expect(math.isNan(exp2(math.nan(f64))));
|
||||
}
|
||||
26
lib/compiler_rt/extenddftf2.zig
Normal file
26
lib/compiler_rt/extenddftf2.zig
Normal file
@ -0,0 +1,26 @@
|
||||
const common = @import("./common.zig");
|
||||
const extendf = @import("./extendf.zig").extendf;
|
||||
|
||||
pub const panic = common.panic;
|
||||
|
||||
comptime {
|
||||
if (common.want_ppc_abi) {
|
||||
@export(__extenddfkf2, .{ .name = "__extenddfkf2", .linkage = common.linkage });
|
||||
} else if (common.want_sparc_abi) {
|
||||
@export(_Qp_dtoq, .{ .name = "_Qp_dtoq", .linkage = common.linkage });
|
||||
} else {
|
||||
@export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = common.linkage });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __extenddftf2(a: f64) callconv(.C) f128 {
|
||||
return extendf(f128, f64, @bitCast(u64, a));
|
||||
}
|
||||
|
||||
fn __extenddfkf2(a: f64) callconv(.C) f128 {
|
||||
return extendf(f128, f64, @bitCast(u64, a));
|
||||
}
|
||||
|
||||
fn _Qp_dtoq(c: *f128, a: f64) callconv(.C) void {
|
||||
c.* = extendf(f128, f64, @bitCast(u64, a));
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user