.if !defined(WITH_CTF)
WITH_CTF=1
.endif

.include <bsd.sys.mk>

SRCDIR=${.CURDIR}
INCDIR=${.CURDIR:H}/include

KMOD=	openzfs

.PATH:	${SRCDIR}/avl \
	${SRCDIR}/lua \
	${SRCDIR}/nvpair \
	${SRCDIR}/icp/algs/blake3 \
	${SRCDIR}/icp/algs/edonr \
	${SRCDIR}/icp/algs/sha2 \
	${SRCDIR}/icp/asm-aarch64/blake3 \
	${SRCDIR}/icp/asm-aarch64/sha2 \
	${SRCDIR}/icp/asm-arm/sha2 \
	${SRCDIR}/icp/asm-ppc64/sha2 \
	${SRCDIR}/icp/asm-ppc64/blake3 \
	${SRCDIR}/icp/asm-x86_64/blake3 \
	${SRCDIR}/icp/asm-x86_64/sha2 \
	${SRCDIR}/os/freebsd/spl \
	${SRCDIR}/os/freebsd/zfs \
	${SRCDIR}/unicode \
	${SRCDIR}/zcommon \
	${SRCDIR}/zfs \
	${SRCDIR}/zstd \
	${SRCDIR}/zstd/lib/common \
	${SRCDIR}/zstd/lib/compress \
	${SRCDIR}/zstd/lib/decompress

CFLAGS+= -I${INCDIR}
CFLAGS+= -I${SRCDIR}/icp/include
CFLAGS+= -I${INCDIR}/os/freebsd
CFLAGS+= -I${INCDIR}/os/freebsd/spl
CFLAGS+= -I${INCDIR}/os/freebsd/zfs
CFLAGS+= -I${SRCDIR}/zstd/include
CFLAGS+= -include ${INCDIR}/os/freebsd/spl/sys/ccompile.h
CFLAGS+= -I${.CURDIR}

CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 \
	-DHAVE_UIO_ZEROCOPY -DWITHOUT_NETDUMP -D__KERNEL -D_SYS_CONDVAR_H_ \
	-D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DCOMPAT_FREEBSD11

.if ${MACHINE_ARCH} == "amd64"
CFLAGS+= -D__x86_64 -DHAVE_SSE2 -DHAVE_SSSE3 -DHAVE_SSE4_1 -DHAVE_SSE4_2 \
	-DHAVE_AVX -DHAVE_AVX2 -DHAVE_AVX512F -DHAVE_AVX512VL -DHAVE_AVX512BW
.endif

.if defined(WITH_DEBUG) && ${WITH_DEBUG} == "true"
CFLAGS+= -DZFS_DEBUG -g
.if defined(WITH_INVARIANTS) && ${WITH_INVARIANTS} == "true"
 CFLAGS+= -DINVARIANTS -DWITNESS -DOPENSOLARIS_WITNESS
.endif
.if defined(WITH_O0) && ${WITH_O0} == "true"
 CFLAGS+= -O0
.endif
.else
CFLAGS += -DNDEBUG
.endif

.for _SAN in KASAN KMSAN KUBSAN
.if defined(WITH_${_SAN}) && ${WITH_${_SAN}} == "true"
KERN_OPTS_EXTRA+= ${_SAN}
.endif
.endfor

.if defined(WITH_GCOV) && ${WITH_GCOV} == "true"
CFLAGS+=	 -fprofile-arcs -ftest-coverage
.endif

DEBUG_FLAGS=-g

.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "powerpc" || \
	${MACHINE_ARCH} == "powerpcspe" || ${MACHINE_ARCH} == "arm"
CFLAGS+= -DBITS_PER_LONG=32
.else
CFLAGS+= -DBITS_PER_LONG=64
.endif

SRCS=	vnode_if.h device_if.h bus_if.h

#avl
SRCS+=	avl.c

#icp/algs/blake3
SRCS+=	blake3.c \
	blake3_generic.c \
	blake3_impl.c

.if ${MACHINE_ARCH} == "aarch64"
#icp/asm-aarch64/blake3
SRCS+=	b3_aarch64_sse2.S \
	b3_aarch64_sse41.S
.endif

.if ${MACHINE_ARCH} == "powerpc64le"
#icp/asm-ppc64/blake3
SRCS+=	b3_ppc64le_sse2.S \
	b3_ppc64le_sse41.S
.endif

.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386"
#icp/asm-x86_64/blake3
SRCS+=	blake3_avx2.S \
	blake3_avx512.S \
	blake3_sse2.S \
	blake3_sse41.S
.endif

#icp/algs/edonr
SRCS+=	edonr.c

#icp/algs/sha2
SRCS+=	sha256_impl.c \
	sha2_generic.c \
	sha512_impl.c

.if ${MACHINE_ARCH} == "armv7"
#icp/asm-arm/sha2
SRCS+=	sha256-armv7.S \
	sha512-armv7.S
.endif

.if ${MACHINE_ARCH} == "aarch64"
#icp/asm-aarch64/sha2
SRCS+=	sha256-armv8.S \
	sha512-armv8.S
.endif

.if ${MACHINE_ARCH} == "powerpc64" || ${MACHINE_ARCH} == "powerpc64le"
#icp/asm-ppc64/sha2
SRCS+=	sha256-p8.S \
	sha256-ppc.S \
	sha512-p8.S \
	sha512-ppc.S
.endif

.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386"
#icp/asm-x86_64/sha2
SRCS+=	sha256-x86_64.S \
	sha512-x86_64.S
.endif

#lua
SRCS+=	lapi.c \
	lauxlib.c \
	lbaselib.c \
	lcode.c \
	lcompat.c \
	lcorolib.c \
	lctype.c \
	ldebug.c \
	ldo.c \
	lfunc.c \
	lgc.c \
	llex.c \
	lmem.c \
	lobject.c \
	lopcodes.c \
	lparser.c \
	lstate.c \
	lstring.c \
	lstrlib.c \
	ltable.c \
	ltablib.c \
	ltm.c \
	lvm.c \
	lzio.c

#nvpair
SRCS+=	fnvpair.c \
	nvpair.c \
	nvpair_alloc_fixed.c \
	nvpair_alloc_spl.c

#os/freebsd/spl
SRCS+=	acl_common.c \
	callb.c \
	list.c \
	spl_acl.c \
	spl_cmn_err.c \
	spl_dtrace.c \
	spl_kmem.c \
	spl_kstat.c \
	spl_misc.c \
	spl_policy.c \
	spl_procfs_list.c \
	spl_string.c \
	spl_sunddi.c \
	spl_sysevent.c \
	spl_taskq.c \
	spl_uio.c \
	spl_vfs.c \
	spl_vm.c \
	spl_zlib.c \
	spl_zone.c

.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "powerpc" || \
	${MACHINE_ARCH} == "powerpcspe" || ${MACHINE_ARCH} == "arm"
SRCS+= spl_atomic.c
.endif

#os/freebsd/zfs
SRCS+=	abd_os.c \
	arc_os.c \
	crypto_os.c \
	dmu_os.c \
	event_os.c \
	hkdf.c \
	kmod_core.c \
	spa_os.c \
	sysctl_os.c \
	vdev_geom.c \
	vdev_label_os.c \
	zfs_acl.c \
	zfs_ctldir.c \
	zfs_debug.c \
	zfs_dir.c \
	zfs_file_os.c \
	zfs_ioctl_compat.c \
	zfs_ioctl_os.c \
	zfs_racct.c \
	zfs_vfsops.c \
	zfs_vnops_os.c \
	zfs_znode_os.c \
	zio_crypt.c \
	zvol_os.c

#unicode
SRCS+= 	u8_textprep.c \
	uconv.c

#zcommon
SRCS+=	cityhash.c \
	zfeature_common.c \
	zfs_comutil.c \
	zfs_deleg.c \
	zfs_fletcher_avx512.c \
	zfs_fletcher.c \
	zfs_fletcher_intel.c \
	zfs_fletcher_sse.c \
	zfs_fletcher_superscalar4.c \
	zfs_fletcher_superscalar.c \
	zfs_namecheck.c \
	zfs_prop.c \
	zfs_valstr.c \
	zpool_prop.c \
	zprop_common.c

#zfs
SRCS+=	abd.c \
	aggsum.c \
	arc.c \
	blake3_zfs.c \
	blkptr.c \
	bplist.c \
	bpobj.c \
	bptree.c \
	bqueue.c \
	brt.c \
	btree.c \
	dataset_kstats.c \
	dbuf.c \
	dbuf_stats.c \
	ddt.c \
	ddt_log.c \
	ddt_stats.c \
	ddt_zap.c \
	dmu.c \
	dmu_direct.c \
	dmu_diff.c \
	dmu_object.c \
	dmu_objset.c \
	dmu_recv.c \
	dmu_redact.c \
	dmu_send.c \
	dmu_traverse.c \
	dmu_tx.c \
	dmu_zfetch.c \
	dnode.c \
	dnode_sync.c \
	dsl_bookmark.c \
	dsl_crypt.c \
	dsl_dataset.c \
	dsl_deadlist.c \
	dsl_deleg.c \
	dsl_destroy.c \
	dsl_dir.c \
	dsl_pool.c \
	dsl_prop.c \
	dsl_scan.c \
	dsl_synctask.c \
	dsl_userhold.c \
	edonr_zfs.c \
	fm.c \
	gzip.c \
	lz4.c \
	lz4_zfs.c \
	lzjb.c \
	metaslab.c \
	mmp.c \
	multilist.c \
	objlist.c \
	pathname.c \
	range_tree.c \
	refcount.c \
	rrwlock.c \
	sa.c \
	sha2_zfs.c \
	skein_zfs.c \
	spa.c \
	space_map.c \
	space_reftree.c \
	spa_checkpoint.c \
	spa_config.c \
	spa_errlog.c \
	spa_history.c \
	spa_log_spacemap.c \
	spa_misc.c \
	spa_stats.c \
	txg.c \
	uberblock.c \
	unique.c \
	vdev.c \
	vdev_draid.c \
	vdev_draid_rand.c \
	vdev_file.c \
	vdev_indirect_births.c \
	vdev_indirect.c \
	vdev_indirect_mapping.c \
	vdev_initialize.c \
	vdev_label.c \
	vdev_mirror.c \
	vdev_missing.c \
	vdev_queue.c \
	vdev_raidz.c \
	vdev_raidz_math_avx2.c \
	vdev_raidz_math_avx512bw.c \
	vdev_raidz_math_avx512f.c \
	vdev_raidz_math.c \
	vdev_raidz_math_scalar.c \
	vdev_raidz_math_sse2.c \
	vdev_raidz_math_ssse3.c \
	vdev_rebuild.c \
	vdev_removal.c \
	vdev_root.c \
	vdev_trim.c \
	zap.c \
	zap_leaf.c \
	zap_micro.c \
	zcp.c \
	zcp_get.c \
	zcp_global.c \
	zcp_iter.c \
	zcp_set.c \
	zcp_synctask.c \
	zfeature.c \
	zfs_byteswap.c \
	zfs_chksum.c \
	zfs_fm.c \
	zfs_fuid.c \
	zfs_impl.c \
	zfs_ioctl.c \
	zfs_log.c \
	zfs_onexit.c \
	zfs_quota.c \
	zfs_ratelimit.c \
	zfs_replay.c \
	zfs_rlock.c \
	zfs_sa.c \
	zfs_vnops.c \
	zfs_znode.c \
	zil.c \
	zio.c \
	zio_checksum.c \
	zio_compress.c \
	zio_inject.c \
	zle.c \
	zrlock.c \
	zthr.c \
	zvol.c

#zstd
SRCS+=	zfs_zstd.c

#zstd/common
SRCS+=	entropy_common.c \
	error_private.c \
	fse_decompress.c \
	pool.c \
	xxhash.c \
	zstd_common.c \

#zstd/compress
SRCS+=	fse_compress.c \
	hist.c \
	huf_compress.c \
	zstd_compress.c \
	zstd_compress_literals.c \
	zstd_compress_sequences.c \
	zstd_compress_superblock.c \
	zstd_double_fast.c \
	zstd_fast.c \
	zstd_lazy.c \
	zstd_ldm.c \
	zstd_opt.c

#zstd/decompress
SRCS+=	huf_decompress.c \
	zstd_ddict.c \
	zstd_decompress_block.c \
	zstd_decompress.c

beforeinstall:
.if ${MK_DEBUG_FILES} != "no"
	mtree -eu \
	    -f /etc/mtree/BSD.debug.dist \
	    -p ${DESTDIR}/usr/lib
.endif

.include <bsd.kmod.mk>

# Generated binary search code is particularly bad with this optimization.
# Oddly, range_tree.c is not affected when unrolling is not done and dsl_scan.c
# is not affected when unrolling is done.
# Disable it until the following upstream issue is resolved:
# https://github.com/llvm/llvm-project/issues/62790
.if ${CC} == "clang"
.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64"
CFLAGS.dsl_scan.c= -mllvm -x86-cmov-converter=false
CFLAGS.metaslab.c= -mllvm -x86-cmov-converter=false
CFLAGS.range_tree.c= -mllvm -x86-cmov-converter=false
CFLAGS.zap_micro.c= -mllvm -x86-cmov-converter=false
.endif
.endif

CFLAGS.sysctl_os.c= -include ../zfs_config.h
CFLAGS.xxhash.c+= -include ${SYSDIR}/sys/_null.h

CFLAGS.gcc+= -Wno-pointer-to-int-cast

CFLAGS.abd.c= -Wno-cast-qual
CFLAGS.ddt.c= -Wno-cast-qual
CFLAGS.ddt_log.c= -Wno-cast-qual -Wno-pointer-arith
CFLAGS.ddt_zap.c= -Wno-cast-qual
CFLAGS.dmu.c= -Wno-cast-qual
CFLAGS.dmu_traverse.c= -Wno-cast-qual
CFLAGS.dnode.c= ${NO_WUNUSED_BUT_SET_VARIABLE}
CFLAGS.dsl_deadlist.c= -Wno-cast-qual
CFLAGS.dsl_dir.c= -Wno-cast-qual
CFLAGS.dsl_prop.c= -Wno-cast-qual
CFLAGS.edonr.c= -Wno-cast-qual
CFLAGS.fm.c= -Wno-cast-qual
CFLAGS.hist.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.lapi.c= -Wno-cast-qual
CFLAGS.lcompat.c= -Wno-cast-qual
CFLAGS.ldo.c= ${NO_WINFINITE_RECURSION}
CFLAGS.lobject.c= -Wno-cast-qual
CFLAGS.ltable.c= -Wno-cast-qual
CFLAGS.lvm.c= -Wno-cast-qual
CFLAGS.lz4.c= -Wno-cast-qual
CFLAGS.lz4_zfs.c= -Wno-cast-qual
CFLAGS.nvpair.c= -Wno-cast-qual -DHAVE_RPC_TYPES ${NO_WSTRINGOP_OVERREAD}
CFLAGS.pool.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.pool.c= -U__BMI__ -fno-tree-vectorize
CFLAGS.spa.c= -Wno-cast-qual
CFLAGS.spa_misc.c= -Wno-cast-qual
CFLAGS.spl_string.c= -Wno-cast-qual
CFLAGS.spl_vm.c= -Wno-cast-qual
CFLAGS.spl_zlib.c= -Wno-cast-qual
CFLAGS.u8_textprep.c= -Wno-cast-qual
CFLAGS.vdev_draid.c= -Wno-cast-qual
CFLAGS.vdev_raidz.c= -Wno-cast-qual
CFLAGS.vdev_raidz_math.c= -Wno-cast-qual
CFLAGS.vdev_raidz_math_avx2.c= -Wno-cast-qual -Wno-duplicate-decl-specifier
CFLAGS.vdev_raidz_math_avx512f.c= -Wno-cast-qual -Wno-duplicate-decl-specifier
CFLAGS.vdev_raidz_math_scalar.c= -Wno-cast-qual
CFLAGS.vdev_raidz_math_sse2.c= -Wno-cast-qual -Wno-duplicate-decl-specifier
CFLAGS.zap_leaf.c= -Wno-cast-qual
CFLAGS.zap_micro.c= -Wno-cast-qual
CFLAGS.zcp.c= -Wno-cast-qual
CFLAGS.zfs_fletcher.c= -Wno-cast-qual -Wno-pointer-arith
CFLAGS.zfs_fletcher_avx512.c= -Wno-cast-qual -Wno-pointer-arith
CFLAGS.zfs_fletcher_intel.c= -Wno-cast-qual -Wno-pointer-arith
CFLAGS.zfs_fletcher_sse.c= -Wno-cast-qual -Wno-pointer-arith
CFLAGS.zfs_fm.c= -Wno-cast-qual ${NO_WUNUSED_BUT_SET_VARIABLE}
CFLAGS.zfs_ioctl.c= -Wno-cast-qual
CFLAGS.zfs_log.c= -Wno-cast-qual
CFLAGS.zfs_vnops_os.c= -Wno-pointer-arith
CFLAGS.zfs_zstd.c= -Wno-cast-qual -Wno-pointer-arith
CFLAGS.zil.c= -Wno-cast-qual
CFLAGS.zio.c= -Wno-cast-qual
CFLAGS.zprop_common.c= -Wno-cast-qual
CFLAGS.zrlock.c= -Wno-cast-qual

#zstd
CFLAGS.entropy_common.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.error_private.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.fse_compress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL} ${NO_WUNUSED_BUT_SET_VARIABLE}
CFLAGS.fse_decompress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.huf_compress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.huf_decompress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.xxhash.c+= -U__BMI__ -fno-tree-vectorize
CFLAGS.xxhash.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_common.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_compress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_compress_literals.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_compress_sequences.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_compress_superblock.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL} ${NO_WUNUSED_BUT_SET_VARIABLE}
CFLAGS.zstd_ddict.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_decompress.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_decompress_block.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_double_fast.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_fast.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_lazy.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_ldm.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
CFLAGS.zstd_opt.c= -U__BMI__ -fno-tree-vectorize ${NO_WBITWISE_INSTEAD_OF_LOGICAL}

.if ${MACHINE_ARCH} == "aarch64"

sha256-armv8.o: sha256-armv8.S
	${CC} -c ${CFLAGS:N-mgeneral-regs-only} ${WERROR} ${.IMPSRC} \
	     -o ${.TARGET}
	${CTFCONVERT_CMD}

sha512-armv8.o: sha512-armv8.S
	${CC} -c ${CFLAGS:N-mgeneral-regs-only} ${WERROR} ${.IMPSRC} \
	     -o ${.TARGET}
	${CTFCONVERT_CMD}

b3_aarch64_sse2.o: b3_aarch64_sse2.S
	${CC} -c ${CFLAGS:N-mgeneral-regs-only} ${WERROR} ${.IMPSRC} \
	     -o ${.TARGET}
	${CTFCONVERT_CMD}

b3_aarch64_sse41.o: b3_aarch64_sse41.S
	${CC} -c ${CFLAGS:N-mgeneral-regs-only} ${WERROR} ${.IMPSRC} \
	     -o ${.TARGET}
	${CTFCONVERT_CMD}

.endif
