+static ir_node *select_addr(const select_expression_t *expression)
+{
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+
+ ir_node *compound_addr = expression_to_firm(expression->compound);
+
+ declaration_t *entry = expression->compound_entry;
+ assert(entry->declaration_type == DECLARATION_TYPE_COMPOUND_MEMBER);
+ ir_entity *entity = entry->v.entity;
+
+ assert(entity != NULL);
+
+ ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), compound_addr, entity);
+
+ return sel;
+}
+
+static ir_node *select_to_firm(const select_expression_t *expression)
+{
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+ ir_node *addr = select_addr(expression);
+ type_t *type = revert_automatic_type_conversion(
+ (const expression_t*) expression);
+ type = skip_typeref(type);
+ ir_type *irtype = get_ir_type(type);
+
+ return deref_address(irtype, addr, dbgi);
+}
+
+/* Values returned by __builtin_classify_type. */
+typedef enum gcc_type_class
+{
+ no_type_class = -1,
+ void_type_class,
+ integer_type_class,
+ char_type_class,
+ enumeral_type_class,
+ boolean_type_class,
+ pointer_type_class,
+ reference_type_class,
+ offset_type_class,
+ real_type_class,
+ complex_type_class,
+ function_type_class,
+ method_type_class,
+ record_type_class,
+ union_type_class,
+ array_type_class,
+ string_type_class,
+ set_type_class,
+ file_type_class,
+ lang_type_class
+} gcc_type_class;
+
+static ir_node *classify_type_to_firm(const classify_type_expression_t *const expr)
+{
+ const type_t *const type = expr->type_expression->base.datatype;
+
+ gcc_type_class tc;
+ switch (type->type)
+ {
+ case TYPE_ATOMIC: {
+ const atomic_type_t *const atomic_type = &type->atomic;
+ switch (atomic_type->atype) {
+ /* should not be reached */
+ case ATOMIC_TYPE_INVALID:
+ tc = no_type_class;
+ break;
+
+ /* gcc cannot do that */
+ case ATOMIC_TYPE_VOID:
+ tc = void_type_class;
+ break;
+
+ case ATOMIC_TYPE_CHAR: /* gcc handles this as integer */
+ case ATOMIC_TYPE_SCHAR: /* gcc handles this as integer */
+ case ATOMIC_TYPE_UCHAR: /* gcc handles this as integer */
+ case ATOMIC_TYPE_SHORT:
+ case ATOMIC_TYPE_USHORT:
+ case ATOMIC_TYPE_INT:
+ case ATOMIC_TYPE_UINT:
+ case ATOMIC_TYPE_LONG:
+ case ATOMIC_TYPE_ULONG:
+ case ATOMIC_TYPE_LONGLONG:
+ case ATOMIC_TYPE_ULONGLONG:
+ case ATOMIC_TYPE_BOOL: /* gcc handles this as integer */
+ tc = integer_type_class;
+ break;
+
+ case ATOMIC_TYPE_FLOAT:
+ case ATOMIC_TYPE_DOUBLE:
+ case ATOMIC_TYPE_LONG_DOUBLE:
+ tc = real_type_class;
+ break;
+
+#ifdef PROVIDE_COMPLEX
+ case ATOMIC_TYPE_FLOAT_COMPLEX:
+ case ATOMIC_TYPE_DOUBLE_COMPLEX:
+ case ATOMIC_TYPE_LONG_DOUBLE_COMPLEX:
+ tc = complex_type_class;
+ break;
+ case ATOMIC_TYPE_FLOAT_IMAGINARY:
+ case ATOMIC_TYPE_DOUBLE_IMAGINARY:
+ case ATOMIC_TYPE_LONG_DOUBLE_IMAGINARY:
+ tc = complex_type_class;
+ break;
+#endif
+
+ default:
+ panic("Unimplemented case in classify_type_to_firm().");
+ }
+ break;
+ }
+
+ case TYPE_ARRAY: /* gcc handles this as pointer */
+ case TYPE_FUNCTION: /* gcc handles this as pointer */
+ case TYPE_POINTER: tc = pointer_type_class; break;
+ case TYPE_COMPOUND_STRUCT: tc = record_type_class; break;
+ case TYPE_COMPOUND_UNION: tc = union_type_class; break;
+
+ /* gcc handles this as integer */
+ case TYPE_ENUM: tc = integer_type_class; break;
+
+ default:
+ panic("Unimplemented case in classify_type_to_firm().");
+ }
+
+ dbg_info *const dbgi = get_dbg_info(&expr->expression.source_position);
+ ir_mode *const mode = mode_int;
+ tarval *const tv = new_tarval_from_long(tc, mode);
+ return new_d_Const(dbgi, mode, tv);
+}
+
+static ir_node *function_name_to_firm(
+ const string_literal_expression_t *const expr)
+{
+ if (current_function_name == NULL) {
+ const source_position_t *const src_pos =
+ &expr->expression.source_position;
+ const char *const name = current_function_decl->symbol->string;
+ current_function_name = string_to_firm(src_pos, "__func__", name);
+ }
+
+ return current_function_name;
+}
+
+static ir_node *statement_expression_to_firm(const statement_expression_t *expr)
+{
+ statement_t *statement = expr->statement;
+
+ assert(statement->type == STATEMENT_COMPOUND);
+ return compound_statement_to_firm((compound_statement_t*) statement);
+}
+
+static ir_node *va_start_expression_to_firm(
+ const va_start_expression_t *const expr)
+{
+ ir_type *const method_type = get_ir_type(current_function_decl->type);
+ int const n = get_method_n_params(method_type) - 1;
+ ir_entity *const parm_ent = get_method_value_param_ent(method_type, n);
+ ir_node *const arg_base = get_irg_value_param_base(current_ir_graph);
+ dbg_info *const dbgi =
+ get_dbg_info(&expr->expression.source_position);
+ ir_node *const no_mem = new_NoMem();
+ ir_node *const arg_sel =
+ new_d_simpleSel(dbgi, no_mem, arg_base, parm_ent);
+
+ size_t const parm_size = get_type_size(expr->parameter->type);
+ ir_node *const cnst = new_Const_long(mode_uint, parm_size);
+ ir_node *const add = new_d_Add(dbgi, arg_sel, cnst, mode_P_data);
+ set_value_for_expression(expr->ap, add);
+
+ return NULL;
+}
+
+static ir_node *va_arg_expression_to_firm(const va_arg_expression_t *const expr)
+{
+ ir_type *const irtype = get_ir_type(expr->expression.datatype);
+ ir_node *const ap = expression_to_firm(expr->ap);
+ dbg_info *const dbgi = get_dbg_info(&expr->expression.source_position);
+ ir_node *const res = deref_address(irtype, ap, dbgi);
+
+ size_t const parm_size = get_type_size(expr->expression.datatype);
+ ir_node *const cnst = new_Const_long(mode_uint, parm_size);
+ ir_node *const add = new_d_Add(dbgi, ap, cnst, mode_P_data);
+ set_value_for_expression(expr->ap, add);
+
+ return res;
+}
+
+static ir_node *dereference_addr(const unary_expression_t *const expression)
+{
+ assert(expression->expression.type == EXPR_UNARY_DEREFERENCE);
+ return expression_to_firm(expression->value);
+}
+