162306a36Sopenharmony_ci/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * rseq/compiler.h
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Work-around asm goto compiler bugs.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * (C) Copyright 2021 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef RSEQ_COMPILER_H
1162306a36Sopenharmony_ci#define RSEQ_COMPILER_H
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/*
1462306a36Sopenharmony_ci * gcc prior to 4.8.2 miscompiles asm goto.
1562306a36Sopenharmony_ci * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci * gcc prior to 8.1.0 miscompiles asm goto at O1.
1862306a36Sopenharmony_ci * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103908
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci * clang prior to version 13.0.1 miscompiles asm goto at O2.
2162306a36Sopenharmony_ci * https://github.com/llvm/llvm-project/issues/52735
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * Work around these issues by adding a volatile inline asm with
2462306a36Sopenharmony_ci * memory clobber in the fallthrough after the asm goto and at each
2562306a36Sopenharmony_ci * label target.  Emit this for all compilers in case other similar
2662306a36Sopenharmony_ci * issues are found in the future.
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_ci#define rseq_after_asm_goto()	asm volatile ("" : : : "memory")
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* Combine two tokens. */
3162306a36Sopenharmony_ci#define RSEQ__COMBINE_TOKENS(_tokena, _tokenb)	\
3262306a36Sopenharmony_ci	_tokena##_tokenb
3362306a36Sopenharmony_ci#define RSEQ_COMBINE_TOKENS(_tokena, _tokenb)	\
3462306a36Sopenharmony_ci	RSEQ__COMBINE_TOKENS(_tokena, _tokenb)
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#ifdef __cplusplus
3762306a36Sopenharmony_ci#define rseq_unqual_scalar_typeof(x)					\
3862306a36Sopenharmony_ci	std::remove_cv<std::remove_reference<decltype(x)>::type>::type
3962306a36Sopenharmony_ci#else
4062306a36Sopenharmony_ci#define rseq_scalar_type_to_expr(type)					\
4162306a36Sopenharmony_ci	unsigned type: (unsigned type)0,				\
4262306a36Sopenharmony_ci	signed type: (signed type)0
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/*
4562306a36Sopenharmony_ci * Use C11 _Generic to express unqualified type from expression. This removes
4662306a36Sopenharmony_ci * volatile qualifier from expression type.
4762306a36Sopenharmony_ci */
4862306a36Sopenharmony_ci#define rseq_unqual_scalar_typeof(x)					\
4962306a36Sopenharmony_ci	__typeof__(							\
5062306a36Sopenharmony_ci		_Generic((x),						\
5162306a36Sopenharmony_ci			char: (char)0,					\
5262306a36Sopenharmony_ci			rseq_scalar_type_to_expr(char),			\
5362306a36Sopenharmony_ci			rseq_scalar_type_to_expr(short),		\
5462306a36Sopenharmony_ci			rseq_scalar_type_to_expr(int),			\
5562306a36Sopenharmony_ci			rseq_scalar_type_to_expr(long),			\
5662306a36Sopenharmony_ci			rseq_scalar_type_to_expr(long long),		\
5762306a36Sopenharmony_ci			default: (x)					\
5862306a36Sopenharmony_ci		)							\
5962306a36Sopenharmony_ci	)
6062306a36Sopenharmony_ci#endif
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#endif  /* RSEQ_COMPILER_H_ */
63