static ir_tarval *builtin_constant_to_tarval( builtin_constant_expression_t const *const expression) { ir_mode *const mode = get_ir_mode_storage(expression->base.type); bool const v = is_constant_expression(expression->value) != EXPR_CLASS_VARIABLE; return create_tarval_from_bool(mode, v); }
bool is_linktime_constant(const expression_t *expression) { switch (expression->kind) { case EXPR_SELECT: /* TODO */ return false; case EXPR_ARRAY_ACCESS: /* TODO */ return false; case EXPR_UNARY_DEREFERENCE: return is_constant_expression(expression->unary.value); default: return false; } }
complex_constant fold_complex(const expression_t *expression) { assert(is_constant_expression(expression) >= EXPR_CLASS_CONSTANT); switch (expression->kind) { case EXPR_BINARY_ADD: return fold_complex_binop(&expression->binary, fold_complex_add); case EXPR_BINARY_SUB: return fold_complex_binop(&expression->binary, fold_complex_sub); case EXPR_BINARY_MUL: return fold_complex_binop(&expression->binary, fold_complex_mul); case EXPR_BINARY_DIV: return fold_complex_binop(&expression->binary, fold_complex_div); case EXPR_UNARY_PLUS: return fold_complex(expression->unary.value); case EXPR_UNARY_NEGATE: return fold_complex_negate(&expression->unary); case EXPR_UNARY_COMPLEMENT: return fold_complex_complement(&expression->unary); case EXPR_LITERAL_INTEGER: case EXPR_LITERAL_FLOATINGPOINT: return fold_complex_literal(&expression->literal); case EXPR_CONDITIONAL: return fold_complex_conditional(&expression->conditional); case EXPR_UNARY_CAST: return fold_complex_cast(&expression->unary); case EXPR_ARRAY_ACCESS: case EXPR_BINARY_ADD_ASSIGN: case EXPR_BINARY_ASSIGN: case EXPR_BINARY_COMMA: case EXPR_BINARY_DIV_ASSIGN: case EXPR_BINARY_MUL_ASSIGN: case EXPR_BINARY_SUB_ASSIGN: case EXPR_CALL: case EXPR_REFERENCE: case EXPR_SELECT: case EXPR_STATEMENT: case EXPR_UNARY_DEREFERENCE: case EXPR_UNARY_POSTFIX_DECREMENT: case EXPR_UNARY_POSTFIX_INCREMENT: case EXPR_UNARY_PREFIX_DECREMENT: case EXPR_UNARY_PREFIX_INCREMENT: panic("invalid expression kind for constant folding"); case NEVER_COMPLEX_CASES: break; } panic("internal error: non-complex expression in fold_complex"); }
bool is_constant_expression(const expression_t *expression) { switch (expression->kind) { case EXPR_INT_CONST: case EXPR_FLOAT_CONST: case EXPR_BOOL_CONST: case EXPR_NULL_POINTER: case EXPR_SIZEOF: return true; case EXPR_STRING_CONST: case EXPR_FUNC: case EXPR_UNARY_INCREMENT: case EXPR_UNARY_DECREMENT: case EXPR_UNARY_DEREFERENCE: case EXPR_BINARY_ASSIGN: case EXPR_SELECT: case EXPR_ARRAY_ACCESS: return false; case EXPR_UNARY_TAKE_ADDRESS: return is_linktime_constant(expression->unary.value); case EXPR_REFERENCE: { entity_t *entity = expression->reference.entity; if (entity->kind == ENTITY_CONSTANT) return true; return false; } case EXPR_CALL: /* TODO: we might introduce pure/side effect free calls */ return false; case EXPR_UNARY_CAST: case EXPR_UNARY_NEGATE: case EXPR_UNARY_NOT: case EXPR_UNARY_BITWISE_NOT: return is_constant_expression(expression->unary.value); case EXPR_BINARY_ADD: case EXPR_BINARY_SUB: case EXPR_BINARY_MUL: case EXPR_BINARY_DIV: case EXPR_BINARY_MOD: case EXPR_BINARY_EQUAL: case EXPR_BINARY_NOTEQUAL: case EXPR_BINARY_LESS: case EXPR_BINARY_LESSEQUAL: case EXPR_BINARY_GREATER: case EXPR_BINARY_GREATEREQUAL: case EXPR_BINARY_AND: case EXPR_BINARY_OR: case EXPR_BINARY_XOR: case EXPR_BINARY_SHIFTLEFT: case EXPR_BINARY_SHIFTRIGHT: /* not that lazy and/or are not constant if their value is clear after * evaluating the left side. This is because we can't (always) evaluate the * left hand side until the ast2firm phase, and therefore can't determine * constness */ case EXPR_BINARY_LAZY_AND: case EXPR_BINARY_LAZY_OR: return is_constant_expression(expression->binary.left) && is_constant_expression(expression->binary.right); case EXPR_ERROR: return true; case EXPR_INVALID: break; } panic("invalid expression in is_constant_expression"); }