#include #define MCPP_INTEGER_BITS 64U static __mpu_int64_t mcpp_semantic_signed( mcpp_integer value ) { if( value.value <= (__mpu_uint64_t)INT64_MAX ) return( (__mpu_int64_t)value.value ); return( -1 - (__mpu_int64_t)(UINT64_MAX - value.value) ); } static __mpu_uint64_t mcpp_semantic_unsigned_from_signed( __mpu_int64_t value ) { if( value >= 0 ) return( (__mpu_uint64_t)value ); return( UINT64_MAX - (__mpu_uint64_t)(-(value + 1)) ); } static unsigned mcpp_semantic_shift_count( mcpp_integer value, int *negative ) { __mpu_uint64_t magnitude; *negative = 0; if( !value.unsignedp && mcpp_semantic_signed(value) < 0 ) { *negative = 1; magnitude = (__mpu_uint64_t)0 - value.value; } else magnitude = value.value; if( magnitude >= MCPP_INTEGER_BITS ) return( MCPP_INTEGER_BITS ); return( (unsigned)magnitude ); } static mcpp_integer mcpp_semantic_shift_left_count( mcpp_integer value, unsigned shift ) { mcpp_integer result; result.unsignedp = value.unsignedp; if( shift >= MCPP_INTEGER_BITS ) result.value = 0; else result.value = value.value << shift; return( result ); } static mcpp_integer mcpp_semantic_shift_right_count( mcpp_integer value, unsigned shift ) { mcpp_integer result; int negative; result.unsignedp = value.unsignedp; negative = !value.unsignedp && mcpp_semantic_signed(value) < 0; if( shift >= MCPP_INTEGER_BITS ) { result.value = negative ? UINT64_MAX : 0; return( result ); } if( shift == 0 || value.unsignedp || !negative ) { result.value = value.value >> shift; return( result ); } result.value = (value.value >> shift) | (UINT64_MAX << (MCPP_INTEGER_BITS - shift)); return( result ); } void mcpp_semantic_context_init( mcpp_semantic_context *context, const char *filename, unsigned line_number, const mcpp_options *options ) { context->filename = filename; context->line_number = line_number; context->options = options; context->failed = 0; } void mcpp_semantic_error( mcpp_semantic_context *context, const char *message ) { if( context->failed ) return; fprintf( stderr, "%s:%u: error: %s\n", context->filename, context->line_number, message ); context->failed = 1; } void mcpp_semantic_warning( mcpp_semantic_context *context, const char *message ) { if( mcpp_diagnostic_warning(context->options, context->filename, context->line_number, "%s", message) != 0 ) context->failed = 1; } int mcpp_semantic_failed( const mcpp_semantic_context *context ) { return( context->failed ); } mcpp_integer mcpp_semantic_make( __mpu_uint64_t value, int unsignedp ) { mcpp_integer result; result.value = value; result.unsignedp = unsignedp ? 1 : 0; return( result ); } int mcpp_semantic_true( mcpp_integer value ) { return( value.value != 0 ); } mcpp_integer mcpp_semantic_neg( mcpp_integer value ) { value.value = (__mpu_uint64_t)0 - value.value; return( value ); } mcpp_integer mcpp_semantic_not( mcpp_integer value ) { return( mcpp_semantic_make(!mcpp_semantic_true(value), 0) ); } mcpp_integer mcpp_semantic_compl( mcpp_integer value ) { value.value = ~value.value; return( value ); } mcpp_integer mcpp_semantic_mul( mcpp_integer left, mcpp_integer right ) { return( mcpp_semantic_make(left.value * right.value, left.unsignedp || right.unsignedp) ); } mcpp_integer mcpp_semantic_div( mcpp_semantic_context *context, mcpp_integer left, mcpp_integer right, int evaluate ) { int unsignedp = left.unsignedp || right.unsignedp; if( right.value == 0 ) { if( evaluate ) mcpp_semantic_error( context, "division by zero in #if expression" ); return( mcpp_semantic_make(0, unsignedp) ); } if( unsignedp ) return( mcpp_semantic_make(left.value / right.value, 1) ); if( mcpp_semantic_signed(left) == INT64_MIN && mcpp_semantic_signed(right) == -1 ) return( mcpp_semantic_make((__mpu_uint64_t)1 << 63, 0) ); return( mcpp_semantic_make( mcpp_semantic_unsigned_from_signed( mcpp_semantic_signed(left) / mcpp_semantic_signed(right)), 0) ); } mcpp_integer mcpp_semantic_mod( mcpp_semantic_context *context, mcpp_integer left, mcpp_integer right, int evaluate ) { int unsignedp = left.unsignedp || right.unsignedp; if( right.value == 0 ) { if( evaluate ) mcpp_semantic_error( context, "division by zero in #if expression" ); return( mcpp_semantic_make(0, unsignedp) ); } if( unsignedp ) return( mcpp_semantic_make(left.value % right.value, 1) ); if( mcpp_semantic_signed(left) == INT64_MIN && mcpp_semantic_signed(right) == -1 ) return( mcpp_semantic_make(0, 0) ); return( mcpp_semantic_make( mcpp_semantic_unsigned_from_signed( mcpp_semantic_signed(left) % mcpp_semantic_signed(right)), 0) ); } mcpp_integer mcpp_semantic_add( mcpp_integer left, mcpp_integer right ) { return( mcpp_semantic_make(left.value + right.value, left.unsignedp || right.unsignedp) ); } mcpp_integer mcpp_semantic_sub( mcpp_integer left, mcpp_integer right ) { return( mcpp_semantic_make(left.value - right.value, left.unsignedp || right.unsignedp) ); } mcpp_integer mcpp_semantic_lshift( mcpp_integer left, mcpp_integer right ) { unsigned shift; int negative; shift = mcpp_semantic_shift_count( right, &negative ); if( negative ) return( mcpp_semantic_shift_right_count(left, shift) ); return( mcpp_semantic_shift_left_count(left, shift) ); } mcpp_integer mcpp_semantic_rshift( mcpp_integer left, mcpp_integer right ) { unsigned shift; int negative; shift = mcpp_semantic_shift_count( right, &negative ); if( negative ) return( mcpp_semantic_shift_left_count(left, shift) ); return( mcpp_semantic_shift_right_count(left, shift) ); } mcpp_integer mcpp_semantic_equal( mcpp_integer left, mcpp_integer right ) { int unsignedp = left.unsignedp || right.unsignedp; int value = unsignedp ? left.value == right.value : mcpp_semantic_signed(left) == mcpp_semantic_signed(right); return( mcpp_semantic_make((__mpu_uint64_t)value, 0) ); } mcpp_integer mcpp_semantic_notequal( mcpp_integer left, mcpp_integer right ) { mcpp_integer result = mcpp_semantic_equal( left, right ); result.value = !result.value; return( result ); } mcpp_integer mcpp_semantic_less( mcpp_integer left, mcpp_integer right ) { int unsignedp = left.unsignedp || right.unsignedp; int value = unsignedp ? left.value < right.value : mcpp_semantic_signed(left) < mcpp_semantic_signed(right); return( mcpp_semantic_make((__mpu_uint64_t)value, 0) ); } mcpp_integer mcpp_semantic_greater( mcpp_integer left, mcpp_integer right ) { int unsignedp = left.unsignedp || right.unsignedp; int value = unsignedp ? left.value > right.value : mcpp_semantic_signed(left) > mcpp_semantic_signed(right); return( mcpp_semantic_make((__mpu_uint64_t)value, 0) ); } mcpp_integer mcpp_semantic_leq( mcpp_integer left, mcpp_integer right ) { int unsignedp = left.unsignedp || right.unsignedp; int value = unsignedp ? left.value <= right.value : mcpp_semantic_signed(left) <= mcpp_semantic_signed(right); return( mcpp_semantic_make((__mpu_uint64_t)value, 0) ); } mcpp_integer mcpp_semantic_geq( mcpp_integer left, mcpp_integer right ) { int unsignedp = left.unsignedp || right.unsignedp; int value = unsignedp ? left.value >= right.value : mcpp_semantic_signed(left) >= mcpp_semantic_signed(right); return( mcpp_semantic_make((__mpu_uint64_t)value, 0) ); } mcpp_integer mcpp_semantic_bitand( mcpp_integer left, mcpp_integer right ) { return( mcpp_semantic_make(left.value & right.value, left.unsignedp || right.unsignedp) ); } mcpp_integer mcpp_semantic_bitxor( mcpp_integer left, mcpp_integer right ) { return( mcpp_semantic_make(left.value ^ right.value, left.unsignedp || right.unsignedp) ); } mcpp_integer mcpp_semantic_bitor( mcpp_integer left, mcpp_integer right ) { return( mcpp_semantic_make(left.value | right.value, left.unsignedp || right.unsignedp) ); } mcpp_integer mcpp_semantic_and( mcpp_integer left, mcpp_integer right ) { return( mcpp_semantic_make(mcpp_semantic_true(left) && mcpp_semantic_true(right), 0) ); } mcpp_integer mcpp_semantic_or( mcpp_integer left, mcpp_integer right ) { return( mcpp_semantic_make(mcpp_semantic_true(left) || mcpp_semantic_true(right), 0) ); } mcpp_integer mcpp_semantic_conditional( mcpp_integer condition, mcpp_integer yes, mcpp_integer no ) { mcpp_integer result = mcpp_semantic_true(condition) ? yes : no; result.unsignedp = yes.unsignedp || no.unsignedp; return( result ); }