diff --git a/wrapperhelper/README.md b/wrapperhelper/README.md index 657540366..e543af374 100644 --- a/wrapperhelper/README.md +++ b/wrapperhelper/README.md @@ -31,12 +31,20 @@ The first file is a `C` file containing every declaration required. The second f The support file may contain pragma declarations of the form ```c -#pragma wrappers type-letters c TYPE +#pragma wrappers type_letters c TYPE +#pragma wrappers type_letters_strict c TYPE ``` -where `TYPE` is a `type-name`. This marks the *exact* type `TYPE` as being a complex type though with a conversion as `c` (which may be multiple characters). Meaning: +where `TYPE` is a `type-name`. The second form marks the *exact* type `TYPE` as being a complex type though with a conversion as `c` (which may be multiple characters), while the first marks the type `TYPE`, regardless of type qualifers (`_Atomic`, `const`, `restrict`, `volatile`). Meaning: - if a parameter has type `TYPE`, the character output will be `c`; - if a parameter has a pointer to `TYPE`, or a structure containing `TYPE`, the output will be a `GOM` function. +Declarations of the form +```c +#pragma wrappers mark_simple TAG +``` +will mark the structure or union with tag `TAG`, or the structure or union aliased to `TAG` by a `typedef` if no such structure exist, as simple. This means that a pointer to such a structure will have a character output of `p`. +This is not the same as making the pointer to the structure a complex type with conversion as `p` as e.g. pointers to pointers will behave differently. + System headers included (directly or indirectly) by the support file are overriden by the files in `include-fixed`. The first three lines of the input are ignored. diff --git a/wrapperhelper/example-libc.h b/wrapperhelper/example-libc.h index b4df17d22..a98260337 100644 --- a/wrapperhelper/example-libc.h +++ b/wrapperhelper/example-libc.h @@ -130,14 +130,7 @@ #include #pragma wrappers type_letters S FILE* -#pragma wrappers type_letters S const FILE* -#pragma wrappers type_letters S FILE* restrict -#pragma wrappers type_letters S const FILE* restrict -#pragma wrappers type_letters p FTS* -#pragma wrappers type_letters p const FTS* -#pragma wrappers type_letters p FTS64* -#pragma wrappers type_letters p const FTS64* -#pragma wrappers type_letters p glob_t* -#pragma wrappers type_letters p const glob_t* -#pragma wrappers type_letters p glob64_t* -#pragma wrappers type_letters p const glob64_t* +#pragma wrappers mark_simple FTS +#pragma wrappers mark_simple FTS64 +#pragma wrappers mark_simple glob_t +#pragma wrappers mark_simple glob64_t diff --git a/wrapperhelper/include-override/aarch64/stdc-predef.h b/wrapperhelper/include-override/aarch64/stdc-predef.h new file mode 100644 index 000000000..bc1f5de37 --- /dev/null +++ b/wrapperhelper/include-override/aarch64/stdc-predef.h @@ -0,0 +1,421 @@ +#define __aarch64__ 1 +#define __AARCH64_CMODEL_SMALL__ 1 +#define __AARCH64EL__ 1 +#define __ARM_64BIT_STATE 1 +#define __ARM_ALIGN_MAX_PWR 28 +#define __ARM_ALIGN_MAX_STACK_PWR 16 +#define __ARM_ARCH 8 +#define __ARM_ARCH_8A 1 +#define __ARM_ARCH_ISA_A64 1 +#define __ARM_ARCH_PROFILE 65 +#define __ARM_FEATURE_CLZ 1 +#define __ARM_FEATURE_FMA 1 +#define __ARM_FEATURE_IDIV 1 +#define __ARM_FEATURE_NUMERIC_MAXMIN 1 +#define __ARM_FEATURE_UNALIGNED 1 +#define __ARM_FP 14 +#define __ARM_FP16_ARGS 1 +#define __ARM_FP16_FORMAT_IEEE 1 +#define __arm_in(...) [[__extension__ arm::in(__VA_ARGS__)]] +#define __arm_inout(...) [[__extension__ arm::inout(__VA_ARGS__)]] +#define __arm_locally_streaming [[__extension__ arm::locally_streaming]] +#define __ARM_NEON 1 +#define __ARM_NEON_SVE_BRIDGE 1 +#define __arm_new(...) [[__extension__ arm::new(__VA_ARGS__)]] +#define __arm_out(...) [[__extension__ arm::out(__VA_ARGS__)]] +#define __ARM_PCS_AAPCS64 1 +#define __arm_preserves(...) [[__extension__ arm::preserves(__VA_ARGS__)]] +#define __ARM_SIZEOF_MINIMAL_ENUM 4 +#define __ARM_SIZEOF_WCHAR_T 4 +#define __ARM_STATE_ZA 1 +#define __ARM_STATE_ZT0 1 +#define __arm_streaming_compatible [[__extension__ arm::streaming_compatible]] +#define __arm_streaming [[__extension__ arm::streaming]] +#define __ATOMIC_ACQ_REL 4 +#define __ATOMIC_ACQUIRE 2 +#define __ATOMIC_CONSUME 1 +#define __ATOMIC_RELAXED 0 +#define __ATOMIC_RELEASE 3 +#define __ATOMIC_SEQ_CST 5 +#define __BFLT16_DECIMAL_DIG__ 4 +#define __BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16 +#define __BFLT16_DIG__ 2 +#define __BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16 +#define __BFLT16_HAS_DENORM__ 1 +#define __BFLT16_HAS_INFINITY__ 1 +#define __BFLT16_HAS_QUIET_NAN__ 1 +#define __BFLT16_IS_IEC_60559__ 0 +#define __BFLT16_MANT_DIG__ 8 +#define __BFLT16_MAX_10_EXP__ 38 +#define __BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16 +#define __BFLT16_MAX_EXP__ 128 +#define __BFLT16_MIN_10_EXP__ (-37) +#define __BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16 +#define __BFLT16_MIN_EXP__ (-125) +#define __BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16 +#define __BIGGEST_ALIGNMENT__ 16 +#define __BITINT_MAXWIDTH__ 65535 +#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ +#define __CHAR16_TYPE__ short unsigned int +#define __CHAR32_TYPE__ unsigned int +#define __CHAR_BIT__ 8 +#define __CHAR_UNSIGNED__ 1 +#define __DBL_DECIMAL_DIG__ 17 +#define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L) +#define __DBL_DIG__ 15 +#define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L) +#define __DBL_HAS_DENORM__ 1 +#define __DBL_HAS_INFINITY__ 1 +#define __DBL_HAS_QUIET_NAN__ 1 +#define __DBL_IS_IEC_60559__ 1 +#define __DBL_MANT_DIG__ 53 +#define __DBL_MAX_10_EXP__ 308 +#define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L) +#define __DBL_MAX_EXP__ 1024 +#define __DBL_MIN_10_EXP__ (-307) +#define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L) +#define __DBL_MIN_EXP__ (-1021) +#define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L) +#define __DEC128_EPSILON__ 1E-33DL +#define __DEC128_MANT_DIG__ 34 +#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL +#define __DEC128_MAX_EXP__ 6145 +#define __DEC128_MIN__ 1E-6143DL +#define __DEC128_MIN_EXP__ (-6142) +#define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL +#define __DEC32_EPSILON__ 1E-6DF +#define __DEC32_MANT_DIG__ 7 +#define __DEC32_MAX__ 9.999999E96DF +#define __DEC32_MAX_EXP__ 97 +#define __DEC32_MIN__ 1E-95DF +#define __DEC32_MIN_EXP__ (-94) +#define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF +#define __DEC64_EPSILON__ 1E-15DD +#define __DEC64_MANT_DIG__ 16 +#define __DEC64_MAX__ 9.999999999999999E384DD +#define __DEC64_MAX_EXP__ 385 +#define __DEC64_MIN__ 1E-383DD +#define __DEC64_MIN_EXP__ (-382) +#define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD +#define __DEC_EVAL_METHOD__ 2 +#define __DECIMAL_BID_FORMAT__ 1 +#define __DECIMAL_DIG__ 36 +#define __ELF__ 1 +#define __FINITE_MATH_ONLY__ 0 +#define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__ +#define __FLT128_DECIMAL_DIG__ 36 +#define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128 +#define __FLT128_DIG__ 33 +#define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128 +#define __FLT128_HAS_DENORM__ 1 +#define __FLT128_HAS_INFINITY__ 1 +#define __FLT128_HAS_QUIET_NAN__ 1 +#define __FLT128_IS_IEC_60559__ 1 +#define __FLT128_MANT_DIG__ 113 +#define __FLT128_MAX_10_EXP__ 4932 +#define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128 +#define __FLT128_MAX_EXP__ 16384 +#define __FLT128_MIN_10_EXP__ (-4931) +#define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128 +#define __FLT128_MIN_EXP__ (-16381) +#define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128 +#define __FLT16_DECIMAL_DIG__ 5 +#define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16 +#define __FLT16_DIG__ 3 +#define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16 +#define __FLT16_HAS_DENORM__ 1 +#define __FLT16_HAS_INFINITY__ 1 +#define __FLT16_HAS_QUIET_NAN__ 1 +#define __FLT16_IS_IEC_60559__ 1 +#define __FLT16_MANT_DIG__ 11 +#define __FLT16_MAX_10_EXP__ 4 +#define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16 +#define __FLT16_MAX_EXP__ 16 +#define __FLT16_MIN_10_EXP__ (-4) +#define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16 +#define __FLT16_MIN_EXP__ (-13) +#define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16 +#define __FLT32_DECIMAL_DIG__ 9 +#define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32 +#define __FLT32_DIG__ 6 +#define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32 +#define __FLT32_HAS_DENORM__ 1 +#define __FLT32_HAS_INFINITY__ 1 +#define __FLT32_HAS_QUIET_NAN__ 1 +#define __FLT32_IS_IEC_60559__ 1 +#define __FLT32_MANT_DIG__ 24 +#define __FLT32_MAX_10_EXP__ 38 +#define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32 +#define __FLT32_MAX_EXP__ 128 +#define __FLT32_MIN_10_EXP__ (-37) +#define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32 +#define __FLT32_MIN_EXP__ (-125) +#define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32 +#define __FLT32X_DECIMAL_DIG__ 17 +#define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x +#define __FLT32X_DIG__ 15 +#define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x +#define __FLT32X_HAS_DENORM__ 1 +#define __FLT32X_HAS_INFINITY__ 1 +#define __FLT32X_HAS_QUIET_NAN__ 1 +#define __FLT32X_IS_IEC_60559__ 1 +#define __FLT32X_MANT_DIG__ 53 +#define __FLT32X_MAX_10_EXP__ 308 +#define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x +#define __FLT32X_MAX_EXP__ 1024 +#define __FLT32X_MIN_10_EXP__ (-307) +#define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x +#define __FLT32X_MIN_EXP__ (-1021) +#define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x +#define __FLT64_DECIMAL_DIG__ 17 +#define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64 +#define __FLT64_DIG__ 15 +#define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64 +#define __FLT64_HAS_DENORM__ 1 +#define __FLT64_HAS_INFINITY__ 1 +#define __FLT64_HAS_QUIET_NAN__ 1 +#define __FLT64_IS_IEC_60559__ 1 +#define __FLT64_MANT_DIG__ 53 +#define __FLT64_MAX_10_EXP__ 308 +#define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64 +#define __FLT64_MAX_EXP__ 1024 +#define __FLT64_MIN_10_EXP__ (-307) +#define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64 +#define __FLT64_MIN_EXP__ (-1021) +#define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64 +#define __FLT64X_DECIMAL_DIG__ 36 +#define __FLT64X_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F64x +#define __FLT64X_DIG__ 33 +#define __FLT64X_EPSILON__ 1.92592994438723585305597794258492732e-34F64x +#define __FLT64X_HAS_DENORM__ 1 +#define __FLT64X_HAS_INFINITY__ 1 +#define __FLT64X_HAS_QUIET_NAN__ 1 +#define __FLT64X_IS_IEC_60559__ 1 +#define __FLT64X_MANT_DIG__ 113 +#define __FLT64X_MAX_10_EXP__ 4932 +#define __FLT64X_MAX__ 1.18973149535723176508575932662800702e+4932F64x +#define __FLT64X_MAX_EXP__ 16384 +#define __FLT64X_MIN_10_EXP__ (-4931) +#define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x +#define __FLT64X_MIN_EXP__ (-16381) +#define __FLT64X_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F64x +#define __FLT_DECIMAL_DIG__ 9 +#define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F +#define __FLT_DIG__ 6 +#define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F +#define __FLT_EVAL_METHOD__ 0 +#define __FLT_EVAL_METHOD_C99__ 0 +#define __FLT_EVAL_METHOD_TS_18661_3__ 0 +#define __FLT_HAS_DENORM__ 1 +#define __FLT_HAS_INFINITY__ 1 +#define __FLT_HAS_QUIET_NAN__ 1 +#define __FLT_IS_IEC_60559__ 1 +#define __FLT_MANT_DIG__ 24 +#define __FLT_MAX_10_EXP__ 38 +#define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F +#define __FLT_MAX_EXP__ 128 +#define __FLT_MIN_10_EXP__ (-37) +#define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F +#define __FLT_MIN_EXP__ (-125) +#define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F +#define __FLT_RADIX__ 2 +#define __FP_FAST_FMA 1 +#define __FP_FAST_FMAF 1 +#define __FP_FAST_FMAF32 1 +#define __FP_FAST_FMAF32x 1 +#define __FP_FAST_FMAF64 1 +#define __GCC_ASM_FLAG_OUTPUTS__ 1 +#define __GCC_ATOMIC_BOOL_LOCK_FREE 2 +#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2 +#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2 +#define __GCC_ATOMIC_CHAR_LOCK_FREE 2 +#define __GCC_ATOMIC_INT_LOCK_FREE 2 +#define __GCC_ATOMIC_LLONG_LOCK_FREE 2 +#define __GCC_ATOMIC_LONG_LOCK_FREE 2 +#define __GCC_ATOMIC_POINTER_LOCK_FREE 2 +#define __GCC_ATOMIC_SHORT_LOCK_FREE 2 +#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1 +#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2 +#define __GCC_CONSTRUCTIVE_SIZE 64 +#define __GCC_DESTRUCTIVE_SIZE 256 +#define __GCC_HAVE_DWARF2_CFI_ASM 1 +#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1 +#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 1 +#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1 +#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1 +#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1 +#define __GCC_IEC_559 2 +#define __GCC_IEC_559_COMPLEX 2 +#define __GNUC__ 14 +#define __GNUC_EXECUTION_CHARSET_NAME "UTF-8" +#define __GNUC_MINOR__ 2 +#define __GNUC_PATCHLEVEL__ 0 +#define __GNUC_STDC_INLINE__ 1 +#define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE" +#define __gnu_linux__ 1 +#define __GXX_ABI_VERSION 1019 +#define __HAVE_SPECULATION_SAFE_VALUE 1 +#define __INT16_C(c) c +#define __INT16_MAX__ 0x7fff +#define __INT16_TYPE__ short int +#define __INT32_C(c) c +#define __INT32_MAX__ 0x7fffffff +#define __INT32_TYPE__ int +#define __INT64_C(c) c ## L +#define __INT64_MAX__ 0x7fffffffffffffffL +#define __INT64_TYPE__ long int +#define __INT8_C(c) c +#define __INT8_MAX__ 0x7f +#define __INT8_TYPE__ signed char +#define __INT_FAST16_MAX__ 0x7fffffffffffffffL +#define __INT_FAST16_TYPE__ long int +#define __INT_FAST16_WIDTH__ 64 +#define __INT_FAST32_MAX__ 0x7fffffffffffffffL +#define __INT_FAST32_TYPE__ long int +#define __INT_FAST32_WIDTH__ 64 +#define __INT_FAST64_MAX__ 0x7fffffffffffffffL +#define __INT_FAST64_TYPE__ long int +#define __INT_FAST64_WIDTH__ 64 +#define __INT_FAST8_MAX__ 0x7f +#define __INT_FAST8_TYPE__ signed char +#define __INT_FAST8_WIDTH__ 8 +#define __INT_LEAST16_MAX__ 0x7fff +#define __INT_LEAST16_TYPE__ short int +#define __INT_LEAST16_WIDTH__ 16 +#define __INT_LEAST32_MAX__ 0x7fffffff +#define __INT_LEAST32_TYPE__ int +#define __INT_LEAST32_WIDTH__ 32 +#define __INT_LEAST64_MAX__ 0x7fffffffffffffffL +#define __INT_LEAST64_TYPE__ long int +#define __INT_LEAST64_WIDTH__ 64 +#define __INT_LEAST8_MAX__ 0x7f +#define __INT_LEAST8_TYPE__ signed char +#define __INT_LEAST8_WIDTH__ 8 +#define __INT_MAX__ 0x7fffffff +#define __INTMAX_C(c) c ## L +#define __INTMAX_MAX__ 0x7fffffffffffffffL +#define __INTMAX_TYPE__ long int +#define __INTMAX_WIDTH__ 64 +#define __INTPTR_MAX__ 0x7fffffffffffffffL +#define __INTPTR_TYPE__ long int +#define __INTPTR_WIDTH__ 64 +#define __INT_WIDTH__ 32 +#define __LDBL_DECIMAL_DIG__ 36 +#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L +#define __LDBL_DIG__ 33 +#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L +#define __LDBL_HAS_DENORM__ 1 +#define __LDBL_HAS_INFINITY__ 1 +#define __LDBL_HAS_QUIET_NAN__ 1 +#define __LDBL_IS_IEC_60559__ 1 +#define __LDBL_MANT_DIG__ 113 +#define __LDBL_MAX_10_EXP__ 4932 +#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L +#define __LDBL_MAX_EXP__ 16384 +#define __LDBL_MIN_10_EXP__ (-4931) +#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L +#define __LDBL_MIN_EXP__ (-16381) +#define __LDBL_NORM_MAX__ 1.18973149535723176508575932662800702e+4932L +#define __linux 1 +#define __linux__ 1 +#define linux 1 +#define __LONG_LONG_MAX__ 0x7fffffffffffffffLL +#define __LONG_LONG_WIDTH__ 64 +#define __LONG_MAX__ 0x7fffffffffffffffL +#define __LONG_WIDTH__ 64 +#define __LP64__ 1 +#define _LP64 1 +#define __NO_INLINE__ 1 +#define __ORDER_BIG_ENDIAN__ 4321 +#define __ORDER_LITTLE_ENDIAN__ 1234 +#define __ORDER_PDP_ENDIAN__ 3412 +#define __pic__ 2 +#define __PIC__ 2 +#define __pie__ 2 +#define __PIE__ 2 +#define __PRAGMA_REDEFINE_EXTNAME 1 +#define __PTRDIFF_MAX__ 0x7fffffffffffffffL +#define __PTRDIFF_TYPE__ long int +#define __PTRDIFF_WIDTH__ 64 +#define __REGISTER_PREFIX__ +#define __SCHAR_MAX__ 0x7f +#define __SCHAR_WIDTH__ 8 +#define __SHRT_MAX__ 0x7fff +#define __SHRT_WIDTH__ 16 +#define __SIG_ATOMIC_MAX__ 0x7fffffff +#define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1) +#define __SIG_ATOMIC_TYPE__ int +#define __SIG_ATOMIC_WIDTH__ 32 +#define __SIZE_MAX__ 0xffffffffffffffffUL +#define __SIZEOF_DOUBLE__ 8 +#define __SIZEOF_FLOAT__ 4 +#define __SIZEOF_INT128__ 16 +#define __SIZEOF_INT__ 4 +#define __SIZEOF_LONG__ 8 +#define __SIZEOF_LONG_DOUBLE__ 16 +#define __SIZEOF_LONG_LONG__ 8 +#define __SIZEOF_POINTER__ 8 +#define __SIZEOF_PTRDIFF_T__ 8 +#define __SIZEOF_SHORT__ 2 +#define __SIZEOF_SIZE_T__ 8 +#define __SIZEOF_WCHAR_T__ 4 +#define __SIZEOF_WINT_T__ 4 +#define __SIZE_TYPE__ long unsigned int +#define __SIZE_WIDTH__ 64 +#define __STDC__ 1 +#define __STDC_HOSTED__ 1 +#define __STDC_IEC_559__ 1 +#define __STDC_IEC_559_COMPLEX__ 1 +#define __STDC_IEC_60559_BFP__ 201404L +#define __STDC_IEC_60559_COMPLEX__ 201404L +#define __STDC_ISO_10646__ 201706L +#define _STDC_PREDEF_H 1 +#define __STDC_UTF_16__ 1 +#define __STDC_UTF_32__ 1 +#define __STDC_VERSION__ 201710L +#define __UINT16_C(c) c +#define __UINT16_MAX__ 0xffff +#define __UINT16_TYPE__ short unsigned int +#define __UINT32_C(c) c ## U +#define __UINT32_MAX__ 0xffffffffU +#define __UINT32_TYPE__ unsigned int +#define __UINT64_C(c) c ## UL +#define __UINT64_MAX__ 0xffffffffffffffffUL +#define __UINT64_TYPE__ long unsigned int +#define __UINT8_C(c) c +#define __UINT8_MAX__ 0xff +#define __UINT8_TYPE__ unsigned char +#define __UINT_FAST16_MAX__ 0xffffffffffffffffUL +#define __UINT_FAST16_TYPE__ long unsigned int +#define __UINT_FAST32_MAX__ 0xffffffffffffffffUL +#define __UINT_FAST32_TYPE__ long unsigned int +#define __UINT_FAST64_MAX__ 0xffffffffffffffffUL +#define __UINT_FAST64_TYPE__ long unsigned int +#define __UINT_FAST8_MAX__ 0xff +#define __UINT_FAST8_TYPE__ unsigned char +#define __UINT_LEAST16_MAX__ 0xffff +#define __UINT_LEAST16_TYPE__ short unsigned int +#define __UINT_LEAST32_MAX__ 0xffffffffU +#define __UINT_LEAST32_TYPE__ unsigned int +#define __UINT_LEAST64_MAX__ 0xffffffffffffffffUL +#define __UINT_LEAST64_TYPE__ long unsigned int +#define __UINT_LEAST8_MAX__ 0xff +#define __UINT_LEAST8_TYPE__ unsigned char +#define __UINTMAX_C(c) c ## UL +#define __UINTMAX_MAX__ 0xffffffffffffffffUL +#define __UINTMAX_TYPE__ long unsigned int +#define __UINTPTR_MAX__ 0xffffffffffffffffUL +#define __UINTPTR_TYPE__ long unsigned int +#define __unix 1 +#define __unix__ 1 +#define unix 1 +#define __USER_LABEL_PREFIX__ +#define __VERSION__ "14.2.0" +#define __WCHAR_MAX__ 0xffffffffU +#define __WCHAR_MIN__ 0U +#define __WCHAR_TYPE__ unsigned int +#define __WCHAR_WIDTH__ 32 +#define __WINT_MAX__ 0xffffffffU +#define __WINT_MIN__ 0U +#define __WINT_TYPE__ unsigned int +#define __WINT_WIDTH__ 32 diff --git a/wrapperhelper/src/cstring.c b/wrapperhelper/src/cstring.c index 865369159..8dc18b82f 100644 --- a/wrapperhelper/src/cstring.c +++ b/wrapperhelper/src/cstring.c @@ -98,6 +98,16 @@ int string_add_char(string_t *s, char elem) { return 1; } +int string_add_char_at(string_t *s, char elem, size_t idx) { + if (idx == s->ssize) return string_add_char(s, elem); + if (idx > s->ssize) return 0; + if (!string_reserve_grow(s, s->ssize + 1)) return 0; + memmove(s->buf + idx + 1, s->buf + idx, s->ssize + 1 - idx); + ++s->ssize; + s->buf[idx] = elem; + return 1; +} + int string_add_string(string_t *s1, string_t *s2) { if (!string_reserve_grow(s1, s1->ssize + s2->ssize)) return 0; memcpy(s1->buf + s1->ssize, s2->buf, s2->ssize); diff --git a/wrapperhelper/src/cstring.h b/wrapperhelper/src/cstring.h index 15ecd0261..fdb0a718c 100644 --- a/wrapperhelper/src/cstring.h +++ b/wrapperhelper/src/cstring.h @@ -19,6 +19,7 @@ * string_del ---------- Frees a string. Takes the string. * string_steal -------- Frees a string, keeping the content alive. Takes the string. The content (also returned) needs to be freed separately. * string_add_char ----- Add a character at the end. Takes the string and the new character. May increase the string capacity. + * string_add_char_at -- Add a character at a given index. Takes the string, the new character and the index. May increase the string capacity. * string_add_string --- Add a string at the end in-place. Takes both strings. May increase the string capacity. * string_add_cstr ----- Add a C string at the end in-place. Takes both strings. May increase the string capacity. * string_pop ---------- Pops the last character. Takes the string. May reduce the string capacity. @@ -68,6 +69,7 @@ int string_trim(string_t *s); void string_del(string_t *s); char *string_steal(string_t *s); int string_add_char(string_t *s, char elem); +int string_add_char_at(string_t *s, char elem, size_t idx); int string_add_string(string_t *s1, string_t *s2); int string_add_cstr(string_t *s1, const char *s2); void string_pop(string_t *s); diff --git a/wrapperhelper/src/generator.c b/wrapperhelper/src/generator.c index 33ace3694..8839f4843 100644 --- a/wrapperhelper/src/generator.c +++ b/wrapperhelper/src/generator.c @@ -99,7 +99,12 @@ void request_print_check(const request_t *req) { similar = !req->default_comment || (req->val.rty != RQT_FUN); // From comment to no comment is dissimilar if (similar && (req->def.rty != req->val.rty)) similar = 0; if (similar && strcmp(string_content(req->def.fun.typ), string_content(req->val.fun.typ))) { - similar = 0; + // "//GOM(_, .F...)" == "//GOM(_, .FE...)" + similar = req->default_comment + && (req->def.rty == RQT_FUN_MY) + && !strncmp(string_content(req->def.fun.typ), string_content(req->val.fun.typ), 2) + && (string_content(req->val.fun.typ)[2] == 'E') + && !strcmp(string_content(req->def.fun.typ) + 2, string_content(req->val.fun.typ) + 3); } if (!similar) { printf("%s%s: function with %s%sdefault%s%s%s%s%s and dissimilar %ssolved%s%s%s%s%s\n", @@ -703,24 +708,28 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { return ret; } -static int is_simple_type_ptr_to(type_t *typ, int *needs_D, int *needs_my) { +static int is_simple_type_ptr_to(type_t *typ, int *needs_D, int *needs_my, khash_t(conv_map) *conv_map) { if (typ->converted) { // printf("Warning: %s uses a converted type but is not the converted type\n", string_content(obj_name)); *needs_my = 1; + } else if (kh_get(conv_map, conv_map, typ) != kh_end(conv_map)) { + // printf("Warning: %s uses a converted type but is not the converted type\n", string_content(obj_name)); + *needs_my = 1; } switch (typ->typ) { case TYPE_BUILTIN: return 1; // Assume pointers to builtin are simple case TYPE_ARRAY: if (typ->val.array.array_sz == (size_t)-1) return 0; // VLA are not simple - return is_simple_type_ptr_to(typ->val.array.typ, needs_D, needs_my); + return is_simple_type_ptr_to(typ->val.array.typ, needs_D, needs_my, conv_map); case TYPE_STRUCT_UNION: if (typ->_internal_use) return 1; // Recursive structures are OK as long as every other members are OK if (!typ->val.st->is_defined) return 1; // Undefined structures are OK since they are opaque + if (typ->val.st->is_simple) return 1; typ->_internal_use = 1; for (size_t i = 0; i < typ->val.st->nmembers; ++i) { st_member_t *mem = &typ->val.st->members[i]; - if (!is_simple_type_ptr_to(mem->typ, needs_D, needs_my)) { + if (!is_simple_type_ptr_to(mem->typ, needs_D, needs_my, conv_map)) { typ->_internal_use = 0; return 0; } @@ -728,9 +737,9 @@ static int is_simple_type_ptr_to(type_t *typ, int *needs_D, int *needs_my) { typ->_internal_use = 0; return 1; case TYPE_ENUM: - return is_simple_type_ptr_to(typ->val.typ, needs_D, needs_my); + return is_simple_type_ptr_to(typ->val.typ, needs_D, needs_my, conv_map); case TYPE_PTR: - return is_simple_type_ptr_to(typ->val.typ, needs_D, needs_my); + return is_simple_type_ptr_to(typ->val.typ, needs_D, needs_my, conv_map); case TYPE_FUNCTION: *needs_my = 1; return 1; @@ -739,10 +748,13 @@ static int is_simple_type_ptr_to(type_t *typ, int *needs_D, int *needs_my) { return 0; } } -static int is_simple_type(type_t *typ, int *needs_D, int *needs_my) { +static int is_simple_type(type_t *typ, int *needs_D, int *needs_my, khash_t(conv_map) *conv_map) { if (typ->converted) { // printf("Warning: %s uses a converted type but is not the converted type\n", string_content(obj_name)); *needs_my = 1; + } else if (kh_get(conv_map, conv_map, typ) != kh_end(conv_map)) { + // printf("Warning: %s uses a converted type but is not the converted type\n", string_content(obj_name)); + *needs_my = 1; } switch (typ->typ) { case TYPE_BUILTIN: @@ -751,7 +763,7 @@ static int is_simple_type(type_t *typ, int *needs_D, int *needs_my) { && (typ->val.builtin != BTT_IFLOAT128); // Assume builtin are simple except for __float128 case TYPE_ARRAY: if (typ->val.array.array_sz == (size_t)-1) return 0; // VLA are not simple - return is_simple_type_ptr_to(typ->val.array.typ, needs_D, needs_my); + return is_simple_type_ptr_to(typ->val.array.typ, needs_D, needs_my, conv_map); case TYPE_STRUCT_UNION: if (typ->_internal_use) return 1; // Recursive structures are OK as long as every other members are OK // if (!typ->val.st->is_defined) return 1; // Undefined structures are OK since they are opaque @@ -760,7 +772,7 @@ static int is_simple_type(type_t *typ, int *needs_D, int *needs_my) { typ->_internal_use = 1; for (size_t i = 0; i < typ->val.st->nmembers; ++i) { st_member_t *mem = &typ->val.st->members[i]; - if (!is_simple_type(mem->typ, needs_D, needs_my)) { + if (!is_simple_type(mem->typ, needs_D, needs_my, conv_map)) { typ->_internal_use = 0; return 0; } @@ -768,9 +780,9 @@ static int is_simple_type(type_t *typ, int *needs_D, int *needs_my) { typ->_internal_use = 0; return 1; case TYPE_ENUM: - return is_simple_type(typ->val.typ, needs_D, needs_my); + return is_simple_type(typ->val.typ, needs_D, needs_my, conv_map); case TYPE_PTR: - return is_simple_type_ptr_to(typ->val.typ, needs_D, needs_my); + return is_simple_type_ptr_to(typ->val.typ, needs_D, needs_my, conv_map); case TYPE_FUNCTION: // Functions should be handled differently (GO instead of DATA) return 0; @@ -780,10 +792,18 @@ static int is_simple_type(type_t *typ, int *needs_D, int *needs_my) { } } -static int convert_type(string_t *dest, type_t *typ, int is_ret, int *needs_D, int *needs_my, string_t *obj_name) { +static int convert_type(string_t *dest, type_t *typ, int is_ret, int *needs_D, int *needs_my, khash_t(conv_map) *conv_map, string_t *obj_name) { if (typ->converted) { if (!string_add_string(dest, typ->converted)) { - printf("Error: failed to add explicit type char\n"); + printf("Error: failed to add explicit type conversion\n"); + return 0; + } + return 1; + } + khiter_t it = kh_get(conv_map, conv_map, typ); + if (it != kh_end(conv_map)) { + if (!string_add_string(dest, kh_val(conv_map, it))) { + printf("Error: failed to add explicit type conversion\n"); return 0; } return 1; @@ -882,15 +902,15 @@ static int convert_type(string_t *dest, type_t *typ, int is_ret, int *needs_D, i } } else { if (typ->val.st->nmembers == 1) { - return convert_type(dest, typ->val.st->members[0].typ, is_ret, needs_D, needs_my, obj_name); + return convert_type(dest, typ->val.st->members[0].typ, is_ret, needs_D, needs_my, conv_map, obj_name); } printf("TODO: convert_type on structure as argument (%s)\n", string_content(obj_name)); return 0; } case TYPE_ENUM: - return convert_type(dest, typ->val.typ, is_ret, needs_D, needs_my, obj_name); + return convert_type(dest, typ->val.typ, is_ret, needs_D, needs_my, conv_map, obj_name); case TYPE_PTR: - if (is_simple_type_ptr_to(typ->val.typ, needs_D, needs_my)) { + if (is_simple_type_ptr_to(typ->val.typ, needs_D, needs_my, conv_map)) { if (!string_add_char(dest, 'p')) { printf("Error: failed to add type char for simple pointer\n"); return 0; @@ -944,26 +964,22 @@ static int convert_type_post(string_t *dest, type_t *typ, string_t *obj_name) { } } -int solve_request(request_t *req, type_t *typ) { +int solve_request(request_t *req, type_t *typ, khash_t(conv_map) *conv_map) { if (typ->typ == TYPE_FUNCTION) { int needs_D = 0, needs_my = req->def.fun.typ && (req->def.rty == RQT_FUN_MY), needs_2 = 0; int convert_post; + size_t idx_conv; req->val.fun.typ = string_new(); if (!req->val.fun.typ) { printf("Error: failed to create function type string\n"); return 0; } - if (!convert_type(req->val.fun.typ, typ->val.fun.ret, 1, &needs_D, &needs_my, req->obj_name)) goto fun_fail; + if (!convert_type(req->val.fun.typ, typ->val.fun.ret, 1, &needs_D, &needs_my, conv_map, req->obj_name)) goto fun_fail; + idx_conv = string_len(req->val.fun.typ); if (!string_add_char(req->val.fun.typ, 'F')) { printf("Error: failed to add convention char\n"); goto fun_fail; } - if (req->def.fun.typ && (req->def.rty == RQT_FUN_MY) && (string_content(req->def.fun.typ)[2] == 'E')) { - if (!string_add_char(req->val.fun.typ, 'E')) { - printf("Error: failed to add emu char\n"); - goto fun_fail; - } - } convert_post = convert_type_post(req->val.fun.typ, typ->val.fun.ret, req->obj_name); if (!convert_post) goto fun_fail; if (typ->val.fun.nargs == (size_t)-1) { @@ -983,7 +999,7 @@ int solve_request(request_t *req, type_t *typ) { } } else { for (size_t i = 0; i < typ->val.fun.nargs; ++i) { - if (!convert_type(req->val.fun.typ, typ->val.fun.args[i], 0, &needs_D, &needs_my, req->obj_name)) goto fun_fail; + if (!convert_type(req->val.fun.typ, typ->val.fun.args[i], 0, &needs_D, &needs_my, conv_map, req->obj_name)) goto fun_fail; } if (typ->val.fun.has_varargs) { if (req->def.fun.typ @@ -1008,6 +1024,13 @@ int solve_request(request_t *req, type_t *typ) { } // fun_succ: + // Add 'E' by default + if (needs_my) { + if (!string_add_char_at(req->val.fun.typ, 'E', idx_conv + 1)) { + printf("Error: failed to add emu char\n"); + goto fun_fail; + } + } if (req->def.fun.typ && (req->def.rty == RQT_FUN_2) && !needs_my) { needs_2 = 1; req->val.fun.fun2 = string_dup(req->def.fun.fun2); @@ -1041,7 +1064,7 @@ int solve_request(request_t *req, type_t *typ) { return 0; } else { int needs_D = 0, needs_my = req->def.dat.has_size && (req->def.rty == RQT_DATAM); - if (is_simple_type(typ, &needs_D, &needs_my)) { + if (is_simple_type(typ, &needs_D, &needs_my, conv_map)) { // TODO: Hmm... req->val.rty = needs_my ? RQT_DATAM : req->def.rty; req->val.dat.has_size = 1; @@ -1056,24 +1079,30 @@ int solve_request(request_t *req, type_t *typ) { } } } -int solve_request_map(request_t *req, khash_t(type_map) *decl_map) { - khiter_t it = kh_get(type_map, decl_map, string_content(req->obj_name)); +int solve_request_map(request_t *req, khash_t(decl_map) *decl_map, khash_t(conv_map) *conv_map) { + khiter_t it = kh_get(decl_map, decl_map, string_content(req->obj_name)); if (it == kh_end(decl_map)) { if (string_content(req->obj_name)[0] != '_') { printf("Error: %s was not declared\n", string_content(req->obj_name)); } return 0; } - return solve_request(req, kh_val(decl_map, it)); + if ((kh_val(decl_map, it)->storage == STORAGE_STATIC) || (kh_val(decl_map, it)->storage == STORAGE_TLS_STATIC)) { + if (string_content(req->obj_name)[0] != '_') { + printf("Error: %s was not declared\n", string_content(req->obj_name)); + } + return 0; + } + return solve_request(req, kh_val(decl_map, it)->typ, conv_map); } -int solve_references(VECTOR(references) *refs, khash_t(type_map) *decl_map) { +int solve_references(VECTOR(references) *refs, khash_t(decl_map) *decl_map, khash_t(conv_map) *conv_map) { int ret = 1; int cond_depth = 0, ok_depth = 0; vector_for(references, ref, refs) { switch (ref->typ) { case REF_REQ: if (ok_depth == cond_depth) { - if (!solve_request_map(&ref->req, decl_map)) ret = 0; + if (!solve_request_map(&ref->req, decl_map, conv_map)) ret = 0; } else { ref->req.ignored = 1; } diff --git a/wrapperhelper/src/generator.h b/wrapperhelper/src/generator.h index 8e892f0ed..59115eb0d 100644 --- a/wrapperhelper/src/generator.h +++ b/wrapperhelper/src/generator.h @@ -57,8 +57,8 @@ void references_print_check(const VECTOR(references) *refs); void output_from_references(FILE *f, const VECTOR(references) *reqs); VECTOR(references) *references_from_file(const char *filename, FILE *f); // Takes ownership of f -int solve_request(request_t *req, type_t *typ); -int solve_request_map(request_t *req, khash_t(type_map) *decl_map); -int solve_references(VECTOR(references) *reqs, khash_t(type_map) *decl_map); +int solve_request(request_t *req, type_t *typ, khash_t(conv_map) *conv_map); +int solve_request_map(request_t *req, khash_t(decl_map) *decl_map, khash_t(conv_map) *conv_map); +int solve_references(VECTOR(references) *reqs, khash_t(decl_map) *decl_map, khash_t(conv_map) *conv_map); #endif // GENERATOR_H diff --git a/wrapperhelper/src/lang.c b/wrapperhelper/src/lang.c index 65c8c7428..8aaacc366 100644 --- a/wrapperhelper/src/lang.c +++ b/wrapperhelper/src/lang.c @@ -84,7 +84,9 @@ void proc_token_del(proc_token_t *tok) { break; case PTOK_PRAGMA: switch (tok->tokv.pragma.typ) { + case PRAGMA_SIMPLE_SU: case PRAGMA_EXPLICIT_CONV: + case PRAGMA_EXPLICIT_CONV_STRICT: string_del(tok->tokv.pragma.val); break; case PRAGMA_ALLOW_INTS: @@ -289,8 +291,14 @@ void proc_token_print(const proc_token_t *tok) { case PRAGMA_ALLOW_INTS: printf("Token: %7s Allow ints\n", "PRAGMA"); break; + case PRAGMA_SIMPLE_SU: + printf("Token: %7s Mark simple: struct or union %s is simple\n", "PRAGMA", string_content(tok->tokv.pragma.val)); + break; case PRAGMA_EXPLICIT_CONV: - printf("Token: %7s Explicit conversion: destination is %s\n", "PRAGMA", string_content(tok->tokv.pragma.val)); + printf("Token: %7s Relaxed explicit conversion: destination is %s\n", "PRAGMA", string_content(tok->tokv.pragma.val)); + break; + case PRAGMA_EXPLICIT_CONV_STRICT: + printf("Token: %7s Strict explicit conversion: destination is %s\n", "PRAGMA", string_content(tok->tokv.pragma.val)); break; default: printf("Token: %7s ???\n", "PRAGMA"); @@ -340,6 +348,7 @@ int proc_token_isend(const proc_token_t *tok) { #pragma GCC diagnostic ignored "-Wanalyzer-null-dereference" KHASH_MAP_IMPL_STR(str2kw, enum token_keyword_type_e) KHASH_MAP_IMPL_STR(type_map, type_t*) +KHASH_MAP_IMPL_STR(decl_map, declaration_t*) KHASH_MAP_IMPL_STR(struct_map, struct_t*) KHASH_MAP_IMPL_STR(const_map, num_constant_t) #pragma GCC diagnostic pop @@ -622,11 +631,21 @@ void type_map_del(khash_t(type_map) *map) { #pragma GCC diagnostic pop kh_destroy(type_map, map); } +void conv_map_del(khash_t(conv_map) *map) { + type_t *typ; + string_t **conv; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" + kh_foreach_key_value_ref(map, typ, conv, type_del(typ); string_del(*conv)) +#pragma GCC diagnostic pop + kh_destroy(conv_map, map); +} void type_set_del(khash_t(type_set) *set) { type_t *it; kh_foreach_key(set, it, type_del(it)) kh_destroy(type_set, set); } + void const_map_del(khash_t(const_map) *map) { kh_cstr_t str; #pragma GCC diagnostic push @@ -636,6 +655,20 @@ void const_map_del(khash_t(const_map) *map) { kh_destroy(const_map, map); } +void decl_del(declaration_t *decl) { + type_del(decl->typ); + free(decl); +} +void decl_map_del(khash_t(decl_map) *map) { + kh_cstr_t str; + declaration_t **it; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" + kh_foreach_key_value_ref(map, str, it, free((void*)str); decl_del(*it)) +#pragma GCC diagnostic pop + kh_destroy(decl_map, map); +} + void st_member_del(st_member_t *member) { if (member->name) string_del(member->name); type_del(member->typ); @@ -693,49 +726,6 @@ type_t *type_new_ptr(type_t *target) { ret->val.typ = target; return ret; } -// The following functions do not work for functions (val.args needs to be duplicated) -/* type_t *type_do_copy(type_t *ref) { - type_t *ret = type_do_copy_nodec(ref); - if (!ret) return NULL; - type_del(ref); - return ret; -} -type_t *type_do_copy_nodec(const type_t *ref) { - type_t *ret = malloc(sizeof *ret); - if (!ret) { - printf("Failed to duplicate type\n"); - return NULL; - } - memcpy(ret, ref, sizeof *ret); - switch (ref->typ) { - case TYPE_BUILTIN: - break; - case TYPE_ARRAY: - ++ref->val.array.typ->nrefs; - break; - case TYPE_STRUCT_UNION: - ++ret->val.st->nrefs; - break; - case TYPE_ENUM: - case TYPE_PTR: - ++ref->val.typ->nrefs; - break; - case TYPE_FUNCTION: - ++ref->val.fun.ret->nrefs; - if (ref->val.fun.nargs != (size_t)-1) { - for (size_t i = 0; i < ref->val.fun.nargs; ++i) { - ++ref->val.fun.args[i]->nrefs; - } - } - break; - } - ret->nrefs = 1; - return ret; -} -type_t *type_maybe_copy(type_t *ref) { - if (ref->nrefs == 1) return ref; - else return type_do_copy(ref); -} */ int type_copy_into(type_t *dest, const type_t *ref) { size_t nrefs = dest->nrefs; _Bool is_atomic = dest->is_atomic; @@ -825,15 +815,16 @@ khint_t type_t_hash(type_t *typ) { default: return 0; } } -int type_t_equal(type_t *typ1, type_t *typ2) { - if (typ1->typ != typ2->typ) return 0; - if ((typ1->is_atomic != typ2->is_atomic) || (typ1->is_const != typ2->is_const) - || (typ1->is_restrict != typ2->is_restrict) || (typ1->is_volatile != typ2->is_volatile)) { +int type_t_equal_aux(type_t *typ1, type_t *typ2, int is_strict) { + if (is_strict && ( + (typ1->is_atomic != typ2->is_atomic) || (typ1->is_const != typ2->is_const) + || (typ1->is_restrict != typ2->is_restrict) || (typ1->is_volatile != typ2->is_volatile))) { return 0; } + if (typ1->typ != typ2->typ) return 0; switch (typ1->typ) { case TYPE_BUILTIN: return typ1->val.builtin == typ2->val.builtin; - case TYPE_ARRAY: return (typ1->val.array.array_sz == typ2->val.array.array_sz) && type_t_equal(typ1->val.array.typ, typ2->val.array.typ); + case TYPE_ARRAY: return (typ1->val.array.array_sz == typ2->val.array.array_sz) && type_t_equal_aux(typ1->val.array.typ, typ2->val.array.typ, is_strict); case TYPE_STRUCT_UNION: // This will not do an infinite recursion since only unnamed struct/unions will compare their members if (!typ1->val.st->tag != !typ2->val.st->tag) return 0; @@ -848,26 +839,33 @@ int type_t_equal(type_t *typ1, type_t *typ2) { if (typ1->val.st->members[i].name && strcmp(string_content(typ1->val.st->members[i].name), string_content(typ2->val.st->members[i].name))) return 0; - if (!type_t_equal(typ1->val.st->members[i].typ, typ2->val.st->members[i].typ)) return 0; + if (!type_t_equal_aux(typ1->val.st->members[i].typ, typ2->val.st->members[i].typ, is_strict)) return 0; } return 1; case TYPE_ENUM: case TYPE_PTR: - return type_t_equal(typ1->val.typ, typ2->val.typ); + return type_t_equal_aux(typ1->val.typ, typ2->val.typ, is_strict); case TYPE_FUNCTION: if (typ1->val.fun.nargs != typ2->val.fun.nargs) return 0; if (typ1->val.fun.has_varargs != typ2->val.fun.has_varargs) return 0; - if (!type_t_equal(typ1->val.fun.ret, typ2->val.fun.ret)) return 0; + if (!type_t_equal_aux(typ1->val.fun.ret, typ2->val.fun.ret, is_strict)) return 0; if (typ1->val.fun.nargs != (size_t)-1) { for (size_t i = 0; i < typ1->val.fun.nargs; ++i) { - if (!type_t_equal(typ1->val.fun.args[i], typ2->val.fun.args[i])) return 0; + if (!type_t_equal_aux(typ1->val.fun.args[i], typ2->val.fun.args[i], is_strict)) return 0; } } return 1; default: return 0; } } +int type_t_equal_lax(type_t *typ1, type_t *typ2) { + return type_t_equal_aux(typ1, typ2, 0); +} +int type_t_equal(type_t *typ1, type_t *typ2) { + return type_t_equal_aux(typ1, typ2, 1); +} __KHASH_IMPL(type_set, , type_t*, char, 0, type_t_hash, type_t_equal) +__KHASH_IMPL(conv_map, , type_t*, string_t*, 1, type_t_hash, type_t_equal_lax) type_t *type_try_merge(type_t *typ, khash_t(type_set) *set) { int iret; @@ -1026,6 +1024,9 @@ void type_print(type_t *typ) { } void struct_print(const struct_t *st) { printf("<" DISP_ADDR_FMT "n_uses=%zu> ", DISP_ADDR_ARG(st) st->nrefs); + if (st->is_simple) { + printf(" "); + } if (st->is_defined) { printf( "%s %s { ", @@ -1071,7 +1072,7 @@ file_t *file_new(machine_t *target) { free(ret); return NULL; } - if (!(ret->decl_map = kh_init(type_map))) { + if (!(ret->decl_map = kh_init(decl_map))) { printf("Failed to create a new translation unit structure (declaration map)\n"); kh_destroy(struct_map, ret->struct_map); kh_destroy(type_map, ret->type_map); @@ -1084,7 +1085,7 @@ file_t *file_new(machine_t *target) { kh_destroy(struct_map, ret->struct_map); kh_destroy(type_map, ret->type_map); kh_destroy(type_map, ret->enum_map); - kh_destroy(type_map, ret->decl_map); + kh_destroy(decl_map, ret->decl_map); free(ret); return NULL; } @@ -1093,8 +1094,19 @@ file_t *file_new(machine_t *target) { kh_destroy(struct_map, ret->struct_map); kh_destroy(type_map, ret->type_map); kh_destroy(type_map, ret->enum_map); - kh_destroy(type_map, ret->decl_map); + kh_destroy(decl_map, ret->decl_map); + kh_destroy(type_set, ret->type_set); + free(ret); + return NULL; + } + if (!(ret->relaxed_type_conversion = kh_init(conv_map))) { + printf("Failed to create a new translation unit structure (relaxed type conversion map)\n"); + kh_destroy(struct_map, ret->struct_map); + kh_destroy(type_map, ret->type_map); + kh_destroy(type_map, ret->enum_map); + kh_destroy(decl_map, ret->decl_map); kh_destroy(type_set, ret->type_set); + kh_destroy(const_map, ret->const_map); free(ret); return NULL; } @@ -1110,8 +1122,9 @@ file_t *file_new(machine_t *target) { } kh_destroy(struct_map, ret->struct_map); kh_destroy(type_map, ret->type_map); + kh_destroy(conv_map, ret->relaxed_type_conversion); kh_destroy(type_map, ret->enum_map); - kh_destroy(type_map, ret->decl_map); + kh_destroy(decl_map, ret->decl_map); kh_destroy(type_set, ret->type_set); kh_destroy(const_map, ret->const_map); free(ret); @@ -1128,8 +1141,9 @@ file_t *file_new(machine_t *target) { printf("Failed to create a new translation unit structure (failed to add intrinsic type to type_set)\n"); kh_destroy(struct_map, ret->struct_map); kh_destroy(type_map, ret->type_map); + kh_destroy(conv_map, ret->relaxed_type_conversion); kh_destroy(type_map, ret->enum_map); - kh_destroy(type_map, ret->decl_map); + kh_destroy(decl_map, ret->decl_map); kh_destroy(type_set, ret->type_set); kh_destroy(const_map, ret->const_map); free(ret); @@ -1141,15 +1155,16 @@ file_t *file_new(machine_t *target) { } kh_destroy(struct_map, ret->struct_map); kh_destroy(type_map, ret->type_map); + kh_destroy(conv_map, ret->relaxed_type_conversion); kh_destroy(type_map, ret->enum_map); - kh_destroy(type_map, ret->decl_map); + kh_destroy(decl_map, ret->decl_map); kh_destroy(type_set, ret->type_set); kh_destroy(const_map, ret->const_map); free(ret); return NULL; } } - // ret is valid + // ret is valid and can now be deleted by file_del // Add __builtin_va_list, __int128_t, __uint128_t as typedef char *sdup; @@ -1183,8 +1198,9 @@ file_t *file_new(machine_t *target) { void file_del(file_t *f) { struct_map_del(f->struct_map); type_map_del(f->type_map); + conv_map_del(f->relaxed_type_conversion); type_map_del(f->enum_map); - type_map_del(f->decl_map); + decl_map_del(f->decl_map); type_set_del(f->type_set); const_map_del(f->const_map); for (enum type_builtin_e i = 0; i < LAST_BUILTIN + 1; ++i) { diff --git a/wrapperhelper/src/lang.h b/wrapperhelper/src/lang.h index 9611df829..e10b85426 100644 --- a/wrapperhelper/src/lang.h +++ b/wrapperhelper/src/lang.h @@ -162,7 +162,9 @@ typedef struct proc_token_s { struct { enum proc_pragma_e { PRAGMA_ALLOW_INTS, + PRAGMA_SIMPLE_SU, PRAGMA_EXPLICIT_CONV, + PRAGMA_EXPLICIT_CONV_STRICT, } typ; string_t *val; } pragma; @@ -375,6 +377,7 @@ typedef struct type_s { } type_t; void type_del(type_t *typ); KHASH_MAP_DECLARE_STR(type_map, type_t*) +KHASH_DECLARE(conv_map, type_t*, string_t*) void type_map_del(khash_t(type_map) *map); int type_t_equal(type_t*, type_t*); @@ -391,6 +394,7 @@ typedef struct struct_s { int is_defined; size_t nrefs; int is_struct; // 0 = union, 1 = struct + int is_simple; // Pointers to the structure (in 64 bits) are simple pointers int has_incomplete; // 1 if the last element of the structure is a VLA or if an element of the union recursively contains a VLA size_t nmembers; st_member_t *members; @@ -401,9 +405,6 @@ KHASH_MAP_DECLARE_STR(struct_map, struct_t*) type_t *type_new(void); // Create a new (complete) builtin type type_t *type_new_ptr(type_t *target); // Create a new pointer type; doesn't increment the use counter of the target -// type_t *type_do_copy(type_t *ref); // Always duplicate ref; decrements the use counter -// type_t *type_do_copy_nodec(const type_t *ref); // Always duplicate ref; doesn't decrements the use counter -// type_t *type_maybe_copy(type_t *ref); // Only duplicate ref if it is used elsewhere; in that case, decrements the use counter int type_copy_into(type_t *dest, const type_t *ref); // Copy ref into dest, keeping additional qualifiers and without changing any use counter struct_t *struct_new(int is_struct, string_t *tag); // Create a new struct @@ -416,11 +417,28 @@ extern const char *builtin2str[LAST_BUILTIN + 1]; void type_print(type_t *typ); void struct_print(const struct_t *st); +typedef struct declaration_s { + enum decl_storage_e { + STORAGE_NONE, + STORAGE_EXTERN, + STORAGE_STATIC, + STORAGE_TLS, + STORAGE_TLS_EXTERN, + STORAGE_TLS_STATIC, + STORAGE_AUTO, + STORAGE_REG, + } storage; + int defined; + type_t *typ; +} declaration_t; +KHASH_MAP_DECLARE_STR(decl_map, declaration_t*) + typedef struct file_s { khash_t(struct_map) *struct_map; khash_t(type_map) *type_map; + khash_t(conv_map) *relaxed_type_conversion; khash_t(type_map) *enum_map; - khash_t(type_map) *decl_map; + khash_t(decl_map) *decl_map; type_t *builtins[LAST_BUILTIN + 1]; khash_t(const_map) *const_map; khash_t(type_set) *type_set; diff --git a/wrapperhelper/src/main.c b/wrapperhelper/src/main.c index 37786f687..84073c485 100644 --- a/wrapperhelper/src/main.c +++ b/wrapperhelper/src/main.c @@ -139,7 +139,7 @@ int main(int argc, char **argv) { return 2; } // vector_for(references, req, refs) request_print(req); - if (!solve_references(refs, content->decl_map)) { + if (!solve_references(refs, content->decl_map, content->relaxed_type_conversion)) { printf("Warning: failed to solve all default requests\n"); } // vector_for(references, req, refs) request_print(req); @@ -171,7 +171,9 @@ int main(int argc, char **argv) { // print content const char *name; struct_t *st; + string_t *str; type_t *typ; + declaration_t *decl; num_constant_t cst; /* for (enum type_builtin_e i = 0; i < LAST_BUILTIN; ++i) { printf("Builtin %u: %p, ", i, content->builtins[i]); @@ -188,6 +190,9 @@ int main(int argc, char **argv) { type_print(typ); printf("\n") ) + kh_foreach(content->relaxed_type_conversion, typ, str, + printf("Type conversion: %p -> %s\n", typ, string_content(str)); + ) kh_foreach(content->type_map, name, typ, printf("Typedef: %s -> %p = ", name, typ); type_print(typ); @@ -211,9 +216,9 @@ int main(int argc, char **argv) { } printf("\n") ) - kh_foreach(content->decl_map, name, typ, - printf("Declaration: %s -> %p = ", name, typ); - type_print(typ); + kh_foreach(content->decl_map, name, decl, + printf("Declaration: %s -> %p = %u/%p: ", name, decl, decl->storage, decl->typ); + type_print(decl->typ); printf("\n") ) file_del(content); diff --git a/wrapperhelper/src/parse.c b/wrapperhelper/src/parse.c index b1f9ed90b..2470d8ce8 100644 --- a/wrapperhelper/src/parse.c +++ b/wrapperhelper/src/parse.c @@ -47,15 +47,26 @@ void dump_preproc(machine_t *target, const char *filename, FILE *file) { } enum decl_storage { - STORAGE_NONE, - STORAGE_TYPEDEF, - STORAGE_EXTERN, - STORAGE_STATIC, - STORAGE_TLS, - STORAGE_TLS_EXTERN, - STORAGE_TLS_STATIC, - STORAGE_AUTO, - STORAGE_REG, + TMPSTO_NONE, + TMPSTO_TYPEDEF, + TMPSTO_EXTERN, + TMPSTO_STATIC, + TMPSTO_TLS, + TMPSTO_TLS_EXTERN, + TMPSTO_TLS_STATIC, + TMPSTO_AUTO, + TMPSTO_REG, +}; +const enum decl_storage_e tmpsto2sto[] = { + [TMPSTO_NONE] = STORAGE_NONE, + [TMPSTO_TYPEDEF] = STORAGE_NONE, + [TMPSTO_EXTERN] = STORAGE_EXTERN, + [TMPSTO_STATIC] = STORAGE_STATIC, + [TMPSTO_TLS] = STORAGE_TLS, + [TMPSTO_TLS_EXTERN] = STORAGE_TLS_EXTERN, + [TMPSTO_TLS_STATIC] = STORAGE_TLS_STATIC, + [TMPSTO_AUTO] = STORAGE_AUTO, + [TMPSTO_REG] = STORAGE_REG, }; enum decl_spec { SPEC_NONE, @@ -84,7 +95,7 @@ static int validate_storage_type(machine_t *target, enum decl_storage storage, // We may still do adjustments here if (!validate_type(target, typ)) return 0; if (typ->typ == TYPE_FUNCTION) { - if ((storage == STORAGE_TLS) || (storage == STORAGE_TLS_EXTERN) || (storage == STORAGE_TLS_STATIC)) { + if ((storage == TMPSTO_TLS) || (storage == TMPSTO_TLS_EXTERN) || (storage == TMPSTO_TLS_STATIC)) { printf("Error: functions cannot be thread local\n"); return 0; } @@ -94,7 +105,7 @@ static int validate_storage_type(machine_t *target, enum decl_storage storage, return VALIDATION_FUN; } } else { - if ((sym == SYM_COMMA) || (sym == SYM_RPAREN) || (sym == SYM_SEMICOLON) || ((storage != STORAGE_TYPEDEF) && (sym == SYM_EQ))) { + if ((sym == SYM_COMMA) || (sym == SYM_RPAREN) || (sym == SYM_SEMICOLON) || ((storage != TMPSTO_TYPEDEF) && (sym == SYM_EQ))) { return (sym == SYM_SEMICOLON) ? VALIDATION_LAST_DECL : VALIDATION_DECL; } } @@ -436,7 +447,7 @@ static int parse_type_name(machine_t *target, khash_t(struct_map) *struct_map, k dest2.argt.type_set = type_set; dest2.argt.builtins = builtins; dest2.argt.const_map = const_map; - if (!parse_declarator(target, &dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, *typ, 0, 0, 0, 1)) { + if (!parse_declarator(target, &dest2, prep, tok, TMPSTO_NONE, FSPEC_NONE, *typ, 0, 0, 0, 1)) { // Token is deleted type_del(*typ); goto failed; @@ -1260,6 +1271,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan if (e->val.cast.typ->typ == TYPE_BUILTIN) { switch (e->val.cast.typ->val.builtin) { case BTT_UCHAR: + case BTT_U8: switch (dest->typ) { case NCT_FLOAT: dest->val.u32 = (uint8_t)dest->val.f; break; case NCT_DOUBLE: dest->val.u32 = (uint8_t)dest->val.d; break; @@ -1272,6 +1284,8 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan dest->typ = NCT_UINT32; return 1; case BTT_INT: + case BTT_SINT: + case BTT_S32: switch (dest->typ) { case NCT_FLOAT: dest->val.i32 = (int32_t)dest->val.f; break; case NCT_DOUBLE: dest->val.i32 = (int32_t)dest->val.d; break; @@ -1283,8 +1297,23 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan } dest->typ = NCT_INT32; return 1; + case BTT_UINT: + case BTT_U32: + switch (dest->typ) { + case NCT_FLOAT: dest->val.u32 = (uint32_t)dest->val.f; break; + case NCT_DOUBLE: dest->val.u32 = (uint32_t)dest->val.d; break; + case NCT_LDOUBLE: dest->val.u32 = (uint32_t)dest->val.l; break; + case NCT_INT32: dest->val.u32 = (uint32_t)dest->val.i32; break; + case NCT_UINT32: break; + case NCT_INT64: dest->val.u32 = (uint32_t)dest->val.i64; break; + case NCT_UINT64: dest->val.u32 = (uint32_t)dest->val.u64; break; + } + dest->typ = NCT_UINT32; + return 1; case BTT_ULONG: // Warning: assuming sizeof(long) == 8 on the current target + // TODO: use machine to select between U32 and U64 + case BTT_U64: switch (dest->typ) { case NCT_FLOAT: dest->val.u64 = (uint64_t)dest->val.f; break; case NCT_DOUBLE: dest->val.u64 = (uint64_t)dest->val.d; break; @@ -1296,18 +1325,6 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan } dest->typ = NCT_UINT64; return 1; - case BTT_U32: - switch (dest->typ) { - case NCT_FLOAT: dest->val.u32 = (uint32_t)dest->val.f; break; - case NCT_DOUBLE: dest->val.u32 = (uint32_t)dest->val.d; break; - case NCT_LDOUBLE: dest->val.u32 = (uint32_t)dest->val.l; break; - case NCT_INT32: dest->val.u32 = (uint32_t)dest->val.i32; break; - case NCT_UINT32: break; - case NCT_INT64: dest->val.u32 = (uint32_t)dest->val.i64; break; - case NCT_UINT64: dest->val.u32 = (uint32_t)dest->val.u64; break; - } - dest->typ = NCT_UINT32; - return 1; case BTT_VOID: case BTT_BOOL: case BTT_CHAR: @@ -1315,8 +1332,6 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BTT_SHORT: case BTT_SSHORT: case BTT_USHORT: - case BTT_SINT: - case BTT_UINT: case BTT_LONG: case BTT_SLONG: case BTT_LONGLONG: @@ -1326,12 +1341,9 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BTT_SINT128: case BTT_UINT128: case BTT_S8: - case BTT_U8: case BTT_S16: case BTT_U16: - case BTT_S32: case BTT_S64: - case BTT_U64: case BTT_FLOAT: case BTT_CFLOAT: case BTT_IFLOAT: @@ -1442,7 +1454,7 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s } // Storage if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_AUTO)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_AUTO; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_AUTO; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1450,8 +1462,8 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s *tok = proc_next_token(prep); goto parse_cur_token_decl; } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_EXTERN)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_EXTERN; - else if (*storage == STORAGE_TLS) *storage = STORAGE_TLS_EXTERN; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_EXTERN; + else if (*storage == TMPSTO_TLS) *storage = TMPSTO_TLS_EXTERN; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1459,7 +1471,7 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s *tok = proc_next_token(prep); goto parse_cur_token_decl; } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_REGISTER)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_REG; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_REG; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1467,8 +1479,8 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s *tok = proc_next_token(prep); goto parse_cur_token_decl; } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_STATIC)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_STATIC; - else if (*storage == STORAGE_TLS) *storage = STORAGE_TLS_STATIC; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_STATIC; + else if (*storage == TMPSTO_TLS) *storage = TMPSTO_TLS_STATIC; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1476,9 +1488,9 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s *tok = proc_next_token(prep); goto parse_cur_token_decl; } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_THREAD_LOCAL)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_TLS; - else if (*storage == STORAGE_EXTERN) *storage = STORAGE_TLS_EXTERN; - else if (*storage == STORAGE_STATIC) *storage = STORAGE_TLS_STATIC; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_TLS; + else if (*storage == TMPSTO_EXTERN) *storage = TMPSTO_TLS_EXTERN; + else if (*storage == TMPSTO_STATIC) *storage = TMPSTO_TLS_STATIC; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1486,7 +1498,7 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s *tok = proc_next_token(prep); goto parse_cur_token_decl; } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_TYPEDEF)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_TYPEDEF; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_TYPEDEF; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1775,7 +1787,7 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s "Current state:\n" " storage: %p/%u\n" " spec: %u\n" - " type: ", string_content(tok->tokv.str), storage, storage ? *storage : STORAGE_NONE, *spec); + " type: ", string_content(tok->tokv.str), storage, storage ? *storage : TMPSTO_NONE, *spec); type_print(typ); printf("\n"); string_del(tok->tokv.str); @@ -1848,7 +1860,7 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s "Current state:\n" " storage: %p/%u\n" " spec: %u\n" - " type: ", storage, storage ? *storage : STORAGE_NONE, *spec); + " type: ", storage, storage ? *storage : TMPSTO_NONE, *spec); type_print(typ); printf("\n"); goto failed; @@ -1916,7 +1928,7 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s dest2.structms.builtins = builtins; dest2.structms.const_map = const_map; dest2.structms.dest = members; - if (!parse_declarator(target, &dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, typ2, 0, 1, 1, 1)) { + if (!parse_declarator(target, &dest2, prep, tok, TMPSTO_NONE, FSPEC_NONE, typ2, 0, 1, 1, 1)) { printf("Error parsing struct-declarator-list\n"); vector_del(st_members, members); type_del(typ2); @@ -2215,7 +2227,7 @@ static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *s "Current state:\n" " storage: %p/%u\n" " spec: %u\n" - " type: ", storage, storage ? *storage : STORAGE_NONE, *spec); + " type: ", storage, storage ? *storage : TMPSTO_NONE, *spec); type_print(typ); printf("\n"); proc_token_print(tok); @@ -2334,7 +2346,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d vector_del(types, args); goto failed; } - enum decl_storage storage2 = STORAGE_NONE; + enum decl_storage storage2 = TMPSTO_NONE; enum decl_spec spec2 = SPEC_NONE; if (!parse_declaration_specifier(target, PDECL_STRUCT_MAP, PDECL_TYPE_MAP, PDECL_ENUM_MAP, PDECL_BUILTINS, PDECL_CONST_MAP, PDECL_TYPE_SET, prep, tok, &storage2, NULL, &spec2, typ2)) { @@ -2383,6 +2395,27 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d break; } else if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_COMMA)) { // Unnamed argument + if (typ2->typ == TYPE_ARRAY) { + // Need to convert type to a pointer + type_t *typ3 = type_new(); + if (!typ3) { + printf("Error: failed to allocate new type\n"); + type_del(typ2); + // Empty destructor + goto failed; + } + if (!type_copy_into(typ3, typ2)) { + printf("Error: failed to duplicate array type to temporary type\n"); + type_del(typ3); + type_del(typ2); + // Empty destructor + goto failed; + } + type_del(typ2); + typ3->typ = TYPE_PTR; + typ3->val.typ = typ3->val.array.typ; + typ2 = type_try_merge(typ3, PDECL_TYPE_SET); + } if (!vector_push(types, args, typ2)) { printf("Error: failed to add argument to argument vector\n"); vector_del(types, args); @@ -2403,7 +2436,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d dest2.argt.type_set = PDECL_TYPE_SET; dest2.argt.builtins = PDECL_BUILTINS; dest2.argt.const_map = PDECL_CONST_MAP; - if (!parse_declarator(target, &dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, typ2, 0, 0, 1, 1)) { + if (!parse_declarator(target, &dest2, prep, tok, TMPSTO_NONE, FSPEC_NONE, typ2, 0, 0, 1, 1)) { // Token is deleted vector_del(types, args); type_del(typ2); @@ -2726,22 +2759,39 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d // whereas no argument in function declaration means the function takes an unspecified number of arguments if (typ->val.fun.nargs == (size_t)-1) typ->val.fun.nargs = 0; + declaration_t *decl = malloc(sizeof *decl); + if (!decl) { + printf("Failed to create new declaration\n"); + // Empty destructor + goto failed; + } + decl->storage = tmpsto2sto[storage]; + decl->defined = 1; + decl->typ = typ; + int iret; char *cident = string_steal(cur_ident); cur_ident = NULL; - khiter_t it = kh_put(type_map, dest->f->decl_map, cident, &iret); + khiter_t it = kh_put(decl_map, dest->f->decl_map, cident, &iret); if (iret < 0) { printf("Failed to add function '%s' to the declaration map\n", cident); free(cident); + free(decl); // Empty destructor goto failed; } else if (iret == 0) { - printf("Error: function '%s' is already in the declaration map\n", cident); - free(cident); - // Empty destructor - goto failed; + free(decl); + if (kh_val(dest->f->decl_map, it)->defined) { + printf("Error: function '%s' is already in the declaration map\n", cident); + free(cident); + // Empty destructor + goto failed; + } else { + free(cident); + decl = kh_val(dest->f->decl_map, it); + } } - kh_val(dest->f->decl_map, it) = typ; + kh_val(dest->f->decl_map, it) = decl; // Skip the function body int nlbraces = 0; @@ -2757,13 +2807,14 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d printf("Error: unexpected token in function body\n"); goto failed; } - if (fspec != FSPEC_NONE) { + if ((fspec != FSPEC_NONE) && (typ->typ != TYPE_FUNCTION)) { printf("Error: unexpected function specifier\n"); // Empty destructor goto failed; } - if (storage == STORAGE_TYPEDEF) { + declaration_t *decl = NULL; + if (storage == TMPSTO_TYPEDEF) { if (!is_init || !is_list) { // We are not at the top-level (note that storage is set to NONE in function arguments) printf("Error: invalid function definition\n"); @@ -2793,31 +2844,46 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } else { kh_val(dest->f->type_map, it) = typ; } - } else if ((storage != STORAGE_STATIC) && (storage != STORAGE_TLS_STATIC)) { + } else { if (is_init && is_list) { - // static variables/functions are not exposed + decl = malloc(sizeof *decl); + if (!decl) { + printf("Failed to create new declaration\n"); + // Empty destructor + goto failed; + } + if ((typ->typ == TYPE_FUNCTION) && (storage == TMPSTO_NONE)) + storage = TMPSTO_EXTERN; + decl->storage = tmpsto2sto[storage]; + decl->defined = 0; + decl->typ = typ; + int iret; char *cident = string_steal(cur_ident); cur_ident = NULL; - khiter_t it = kh_put(type_map, dest->f->decl_map, cident, &iret); + khiter_t it = kh_put(decl_map, dest->f->decl_map, cident, &iret); if (iret < 0) { printf("Failed to add '%s' to the declaration map\n", cident); free(cident); + free(decl); // Empty destructor goto failed; } else if (iret == 0) { - /* if ((storage == STORAGE_NONE) || !type_t_equal(typ, kh_val(dest->f->decl_map, it))) { + if (!type_t_equal(typ, kh_val(dest->f->decl_map, it)->typ) + || ((storage == TMPSTO_NONE) && (kh_val(dest->f->decl_map, it)->storage == STORAGE_NONE))) { printf("Error: '%s' is already in the declaration map (storage=%u)\n", cident, storage); free(cident); + free(decl); type_del(typ); // Empty destructor goto failed; - } else */ { - printf("Warning: '%s' is already in the declaration map with the same type\n", cident); + } else { + // OK, this is allowed free(cident); + free(decl); type_del(typ); } } else { - kh_val(dest->f->decl_map, it) = typ; + kh_val(dest->f->decl_map, it) = decl; } } else if (!is_init && !is_list) { if (allow_decl) { @@ -2868,6 +2934,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d printf("Error: unexpected initializer\n"); goto failed; } + if (decl) { + if (decl->defined) { + printf("Error: invalid declaration initializer: variable was already declared\n"); + goto failed; + } + decl->defined = 1; + } *tok = proc_next_token(prep); if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_LBRACKET)) { // { ... } @@ -2920,7 +2993,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d // Try to free some redundant types typ = type_try_merge(typ, PDECL_TYPE_SET); - // storage == STORAGE_NONE + // storage == TMPSTO_NONE *tok = proc_next_token(prep); expr_t *e = parse_expression(target, dest->structms.struct_map, dest->structms.type_map, dest->structms.enum_map, dest->structms.builtins, dest->structms.const_map, dest->structms.type_set, @@ -2955,7 +3028,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d // Empty destructor goto failed; } - if (fspec != FSPEC_NONE) { + if ((fspec != FSPEC_NONE) && (typ->typ != TYPE_FUNCTION)) { printf("Error: unexpected function specifier\n"); // Empty destructor goto failed; @@ -3158,7 +3231,67 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { } } break; } + case PRAGMA_SIMPLE_SU: { + string_t *sutag = tok.tokv.pragma.val; + struct_t *su; + khiter_t it = kh_get(struct_map, ret->struct_map, string_content(sutag)); + if (it != kh_end(ret->struct_map)) { + su = kh_val(ret->struct_map, it); + } else { + it = kh_get(type_map, ret->type_map, string_content(sutag)); + if (it != kh_end(ret->struct_map)) { + type_t *typ2 = kh_val(ret->type_map, it); + if (typ2->typ != TYPE_STRUCT_UNION) { + printf("Error: failed to find struct/union named %s\n", string_content(sutag)); + string_del(sutag); + goto failed; + } + su = typ2->val.st; + } else { + printf("Error: failed to find struct/union named %s\n", string_content(sutag)); + string_del(sutag); + goto failed; + } + } + string_del(sutag); + su->is_simple = 1; + // Empty destructor + break; } case PRAGMA_EXPLICIT_CONV: { + string_t *converted = tok.tokv.pragma.val; + type_t *typ2 = type_new(); + if (!typ2) { + printf("Error: failed to create new type info structure\n"); + string_del(converted); + type_del(typ2); + goto failed; + } + tok = proc_next_token(prep); + if (!parse_type_name(target, ret->struct_map, ret->type_map, ret->enum_map, &ret->builtins, ret->const_map, ret->type_set, + prep, &tok, SYM_SEMICOLON, &typ2)) { + string_del(converted); + goto failed; + } + int iret; + khiter_t it = kh_put(conv_map, ret->relaxed_type_conversion, typ2, &iret); + if (iret < 0) { + printf("Error: failed to add relaxed conversion to type map\n"); + string_del(converted); + type_del(typ2); + // Empty destructor + goto failed; + } else if (iret == 0) { + printf("Error: type already has a relaxed conversion\n"); + string_del(converted); + type_del(typ2); + // Empty destructor + goto failed; + } + string_trim(converted); + kh_val(ret->relaxed_type_conversion, it) = converted; + // Empty destructor + break; } + case PRAGMA_EXPLICIT_CONV_STRICT: { string_t *converted = tok.tokv.pragma.val; type_t *typ2 = type_new(); if (!typ2) { @@ -3175,7 +3308,7 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { } type_del(typ2); // typ2 is in the type set, so it is already used if (typ2->converted) { - printf("Error: type already has a conversion\n"); + printf("Error: type already has a strict conversion\n"); string_del(converted); // Empty destructor goto failed; @@ -3190,7 +3323,7 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { proc_token_del(&tok); goto failed; } else { - enum decl_storage storage = STORAGE_NONE; + enum decl_storage storage = TMPSTO_NONE; enum fun_spec fspec = FSPEC_NONE; enum decl_spec spec = SPEC_NONE; if (!parse_declaration_specifier(target, ret->struct_map, ret->type_map, ret->enum_map, &ret->builtins, ret->const_map, diff --git a/wrapperhelper/src/preproc.c b/wrapperhelper/src/preproc.c index 0f67762a5..bbef68446 100644 --- a/wrapperhelper/src/preproc.c +++ b/wrapperhelper/src/preproc.c @@ -2794,6 +2794,28 @@ static proc_token_t proc_next_token_aux(preproc_t *src) { ret.tokv.pragma.typ = PRAGMA_ALLOW_INTS; return ret; } + } else if (!strcmp(string_content(tok.tokv.str), "mark_simple")) { + string_del(tok.tokv.str); + tok = ppsrc_next_token(src); + if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { + printf("Invalid pragma wrappers explicit_simple directive, skipping until EOL\n"); + goto preproc_hash_err; + } + src->st = PPST_NL; + ret.tokt = PTOK_PRAGMA; + ret.tokv.pragma.typ = PRAGMA_SIMPLE_SU; + ret.tokv.pragma.val = tok.tokv.str; + tok = ppsrc_next_token(src); + while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) { + preproc_token_del(&tok); + tok = ppsrc_next_token(src); + } + if (tok.tokt == PPTOK_INVALID) { + string_del(ret.tokv.pragma.val); + goto start_cur_token; + } else { + return ret; + } } else if (!strcmp(string_content(tok.tokv.str), "type_letters")) { string_del(tok.tokv.str); tok = ppsrc_next_token(src); @@ -2806,6 +2828,18 @@ static proc_token_t proc_next_token_aux(preproc_t *src) { ret.tokv.pragma.typ = PRAGMA_EXPLICIT_CONV; ret.tokv.pragma.val = tok.tokv.str; return ret; + } else if (!strcmp(string_content(tok.tokv.str), "type_letters_exact")) { + string_del(tok.tokv.str); + tok = ppsrc_next_token(src); + if ((tok.tokt != PPTOK_IDENT) && (tok.tokt != PPTOK_IDENT_UNEXP)) { + printf("Invalid pragma wrappers explicit_simple directive, skipping until EOL\n"); + goto preproc_hash_err; + } + src->st = PPST_PRAGMA_EXPLICIT; + ret.tokt = PTOK_PRAGMA; + ret.tokv.pragma.typ = PRAGMA_EXPLICIT_CONV_STRICT; + ret.tokv.pragma.val = tok.tokv.str; + return ret; } else { printf("Unknown pragma wrappers directive '%s', skipping until EOL\n", string_content(tok.tokv.str)); goto preproc_hash_err;