From: Rémi Bernon rbernon@codeweavers.com
--- tools/widl/expr.c | 92 ++++++++++++++++----------------------------- tools/widl/parser.y | 12 +++--- tools/widl/widl.h | 1 - 3 files changed, 39 insertions(+), 66 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 36f5d769d1a..b25ec5ee769 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -187,65 +187,6 @@ expr_t *expr_str( enum expr_type type, char *val ) return e; }
-expr_t *make_exprt(enum expr_type type, expr_t *decl, expr_t *expr) -{ - expr_t *e; - type_t *tref; - - if (decl->u.decl->stgclass != STG_NONE && decl->u.decl->stgclass != STG_REGISTER) - error_loc("invalid storage class for type expression\n"); - - tref = decl->u.decl->type; - - e = xmalloc( sizeof(expr_t) ); - memset( e, 0, sizeof(*e) ); - e->type = type; - e->u.args[0] = decl; - e->u.args[1] = expr; - if (type == EXPR_SIZEOF) - { - /* only do this for types that should be the same on all platforms */ - if (is_integer_type(tref) || is_float_type(tref)) - { - e->is_const = TRUE; - e->cval = type_memsize(tref); - } - } - /* check for cast of constant expression */ - if (type == EXPR_CAST && expr->is_const) - { - if (is_integer_type(tref)) - { - unsigned int cast_type_bits = type_memsize(tref) * 8; - unsigned int cast_mask; - - e->is_const = TRUE; - if (is_signed_integer_type(tref)) - { - cast_mask = (1u << (cast_type_bits - 1)) - 1; - if (expr->cval & (1u << (cast_type_bits - 1))) - e->cval = -((-expr->cval) & cast_mask); - else - e->cval = expr->cval & cast_mask; - } - else - { - /* calculate ((1 << cast_type_bits) - 1) avoiding overflow */ - cast_mask = ((1u << (cast_type_bits - 1)) - 1) | - 1u << (cast_type_bits - 1); - e->cval = expr->cval & cast_mask; - } - } - else - { - e->is_const = TRUE; - e->cval = expr->cval; - } - } - - return e; -} - expr_t *expr_op( enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3 ) { expr_t *e = xmalloc( sizeof(expr_t) ); @@ -346,6 +287,39 @@ expr_t *expr_op( enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr case EXPR_COND: e->cval = expr1->cval ? expr2->cval : expr3->cval; break; + case EXPR_SIZEOF: + /* only do this for types that should be the same on all platforms */ + if (!is_integer_type( expr1->u.decl->type ) && !is_float_type( expr1->u.decl->type )) + e->is_const = FALSE; + else + e->cval = type_memsize( expr1->u.decl->type ); + break; + + case EXPR_CAST: + /* check for cast of constant expression */ + if (!is_integer_type( expr1->u.decl->type )) + e->cval = expr2->cval; + else + { + unsigned int cast_type_bits = type_memsize( expr1->u.decl->type ) * 8; + unsigned int cast_mask; + + if (is_signed_integer_type( expr1->u.decl->type )) + { + cast_mask = (1u << (cast_type_bits - 1)) - 1; + if (expr2->cval & (1u << (cast_type_bits - 1))) + e->cval = -((-expr2->cval) & cast_mask); + else + e->cval = expr2->cval & cast_mask; + } + else + { + /* calculate ((1 << cast_type_bits) - 1) avoiding overflow */ + cast_mask = ((1u << (cast_type_bits - 1)) - 1) | 1u << (cast_type_bits - 1); + e->cval = expr2->cval & cast_mask; + } + } + break; default: e->is_const = FALSE; break; diff --git a/tools/widl/parser.y b/tools/widl/parser.y index edaa27a3e43..c4bf480a765 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -601,7 +601,7 @@ contract_req expr_t *decl = expr_decl( $decl_spec ); if ($decl_spec->type->type_type != TYPE_APICONTRACT) error_loc( "type %s is not an apicontract\n", $decl_spec->type->name ); - $$ = make_exprt( EXPR_GTREQL, decl, contract ); + $$ = expr_op( EXPR_GTREQL, decl, contract, NULL ); } ;
@@ -610,7 +610,7 @@ static_attr expr_t *decl = expr_decl( $decl_spec ); if ($decl_spec->type->type_type != TYPE_INTERFACE) error_loc( "type %s is not an interface\n", $decl_spec->type->name ); - $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); + $$ = expr_op( EXPR_MEMBER, decl, $contract_req, NULL ); } ;
@@ -619,7 +619,7 @@ activatable_attr: expr_t *decl = expr_decl( $decl_spec ); if ($decl_spec->type->type_type != TYPE_INTERFACE) error_loc( "type %s is not an interface\n", $decl_spec->type->name ); - $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); + $$ = expr_op( EXPR_MEMBER, decl, $contract_req, NULL ); } | contract_req { $$ = $contract_req; } /* activatable on the default activation factory */ ; @@ -635,7 +635,7 @@ composable_attr expr_t *decl = expr_decl( $decl_spec ); if ($decl_spec->type->type_type != TYPE_INTERFACE) error_loc( "type %s is not an interface\n", $decl_spec->type->name ); - $$ = make_exprt( EXPR_MEMBER, decl, $contract_req ); + $$ = expr_op( EXPR_MEMBER, decl, $contract_req, NULL ); } ;
@@ -895,11 +895,11 @@ expr: aNUM { $$ = expr_int( $aNUM, strmake( | '(' cast_decl_spec ')' expr[value] %prec CAST { expr_t *decl = expr_decl( $cast_decl_spec ); - $$ = make_exprt( EXPR_CAST, decl, $value ); + $$ = expr_op( EXPR_CAST, decl, $value, NULL ); } | tSIZEOF '(' cast_decl_spec ')' { expr_t *decl = expr_decl( $cast_decl_spec ); - $$ = make_exprt( EXPR_SIZEOF, decl, NULL ); + $$ = expr_op( EXPR_SIZEOF, decl, NULL, NULL ); } | expr[array] '[' expr[index] ']' { $$ = expr_op( EXPR_ARRAY, $array, $index, NULL ); } | '(' expr ')' { $$ = $2; } diff --git a/tools/widl/widl.h b/tools/widl/widl.h index 506d9e39809..aa0f75a70f0 100644 --- a/tools/widl/widl.h +++ b/tools/widl/widl.h @@ -144,7 +144,6 @@ extern expr_t *expr_decl( decl_spec_t *decl ); extern expr_t *expr_int( int val, const char *text ); extern expr_t *expr_double( double val ); extern expr_t *expr_str( enum expr_type type, char *val ); -extern expr_t *make_exprt( enum expr_type type, expr_t *decl, expr_t *expr ); extern expr_t *expr_op( enum expr_type type, expr_t *arg0, expr_t *arg1, expr_t *arg2 );
extern const type_t *expr_resolve_type( const struct expr_loc *expr_loc, const type_t *cont_type, const expr_t *expr );