+static ir_node *conditional_to_firm(const conditional_expression_t *expression)
+{
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+
+ ir_node *cur_block = get_cur_block();
+
+ /* create the true block */
+ ir_node *true_block = new_immBlock();
+
+ ir_node *true_val = expression_to_firm(expression->true_expression);
+ ir_node *true_jmp = new_Jmp();
+
+ /* create the false block */
+ ir_node *false_block = new_immBlock();
+
+ ir_node *false_val = expression_to_firm(expression->false_expression);
+ ir_node *false_jmp = new_Jmp();
+
+ /* create the condition evaluation */
+ set_cur_block(cur_block);
+ create_condition_evaluation(expression->condition, true_block, false_block);
+ mature_immBlock(true_block);
+ mature_immBlock(false_block);
+
+ /* create the common block */
+ ir_node *common_block = new_immBlock();
+ add_immBlock_pred(common_block, true_jmp);
+ add_immBlock_pred(common_block, false_jmp);
+ mature_immBlock(common_block);
+
+ /* TODO improve static semantics, so either both or no values are NULL */
+ if (true_val == NULL || false_val == NULL) return NULL;
+
+ ir_node *in[2] = { true_val, false_val };
+ ir_mode *mode = get_irn_mode(true_val);
+ assert(get_irn_mode(false_val) == mode);
+ ir_node *val = new_d_Phi(dbgi, 2, in, mode);
+
+ return val;
+}
+
+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 = skip_typeref(expression->expression.datatype);
+ return deref_address(type, 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->datatype;
+
+ gcc_type_class tc;
+ switch (type->type)
+ {
+ case TYPE_ATOMIC: {
+ const atomic_type_t *const atomic_type = (const atomic_type_t*)type;
+ 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_Is;
+ 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_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 *dereference_addr(const unary_expression_t *const expression)
+{
+ assert(expression->type == UNEXPR_DEREFERENCE);
+ return expression_to_firm(expression->value);
+}
+