+static ir_entity* get_function_entity(declaration_t *declaration)
+{
+ if(declaration->declaration_type == DECLARATION_TYPE_FUNCTION)
+ return declaration->v.entity;
+ assert(declaration->declaration_type == DECLARATION_TYPE_UNKNOWN);
+
+ symbol_t *symbol = declaration->symbol;
+ ident *id = new_id_from_str(symbol->string);
+
+ ir_type *global_type = get_glob_type();
+ ir_type *ir_type_method = get_ir_type(declaration->type);
+ assert(is_Method_type(ir_type_method));
+
+ type_t *type = declaration->type;
+ ir_entity *entity = new_entity(global_type, id, ir_type_method);
+ set_entity_ld_ident(entity, id);
+ if(declaration->storage_class & STORAGE_CLASS_STATIC
+ || type->qualifiers & TYPE_QUALIFIER_INLINE) {
+ set_entity_visibility(entity, visibility_local);
+ } else if(declaration->init.statement != NULL) {
+ set_entity_visibility(entity, visibility_external_visible);
+ } else {
+ set_entity_visibility(entity, visibility_external_allocated);
+ }
+
+ declaration->declaration_type = DECLARATION_TYPE_FUNCTION;
+ declaration->v.entity = entity;
+
+ return entity;
+}
+
+
+
+static ir_node *expression_to_firm(const expression_t *expression);
+
+static dbg_info *get_dbg_info(const source_position_t *pos)
+{
+ return (dbg_info*) pos;
+}
+
+static ir_node *const_to_firm(const const_t *cnst)
+{
+ dbg_info *dbgi = get_dbg_info(&cnst->expression.source_position);
+ ir_mode *mode = get_ir_mode(cnst->expression.datatype);
+
+ tarval *tv;
+ if(mode_is_float(mode)) {
+ tv = new_tarval_from_double(cnst->v.float_value, mode);
+ } else {
+ tv = new_tarval_from_long(cnst->v.int_value, mode);
+ }
+
+ return new_d_Const(dbgi, mode, tv);
+}
+
+static ir_node *create_symconst(dbg_info *dbgi, ir_entity *entity)
+{
+ assert(entity != NULL);
+ union symconst_symbol sym;
+ sym.entity_p = entity;
+ return new_d_SymConst(dbgi, sym, symconst_addr_ent);
+}
+
+static ir_node *string_literal_to_firm(const string_literal_t* literal)
+{
+ ir_type *global_type = get_glob_type();
+ ir_type *type = new_type_array(unique_ident("strtype"), 1,
+ ir_type_const_char);
+
+ ident *id = unique_ident("Lstr");
+ ir_entity *entity = new_entity(global_type, id, type);
+ set_entity_ld_ident(entity, id);
+ set_entity_variability(entity, variability_constant);
+
+ ir_type *elem_type = ir_type_const_char;
+ ir_mode *mode = get_type_mode(elem_type);
+
+ const char *string = literal->value;
+ size_t slen = strlen(string) + 1;
+
+ set_array_lower_bound_int(type, 0, 0);
+ set_array_upper_bound_int(type, 0, slen);
+ set_type_size_bytes(type, slen);
+ set_type_state(type, layout_fixed);
+
+ tarval **tvs = xmalloc(slen * sizeof(tvs[0]));
+ for(size_t i = 0; i < slen; ++i) {
+ tvs[i] = new_tarval_from_long(string[i], mode);
+ }
+
+ set_array_entity_values(entity, tvs, slen);
+ free(tvs);
+
+ dbg_info *dbgi = get_dbg_info(&literal->expression.source_position);
+
+ return create_symconst(dbgi, entity);
+}
+
+static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
+{
+ dbg_info *dbgi = get_dbg_info(&ref->expression.source_position);
+ declaration_t *declaration = ref->declaration;
+ type_t *type = declaration->type;
+ ir_mode *mode = get_ir_mode(type);
+
+ switch((declaration_type_t) declaration->declaration_type) {
+ case DECLARATION_TYPE_UNKNOWN:
+ break;
+ case DECLARATION_TYPE_LOCAL_VARIABLE:
+ return get_value(declaration->v.value_number, mode);
+ case DECLARATION_TYPE_FUNCTION: {
+ return create_symconst(dbgi, declaration->v.entity);
+ }
+ case DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY:
+ case DECLARATION_TYPE_GLOBAL_VARIABLE:
+ case DECLARATION_TYPE_COMPOUND_MEMBER:
+ panic("not implemented reference type");
+ }
+
+ panic("reference to declaration with unknown type found");
+}
+
+static ir_node *call_expression_to_firm(const call_expression_t *call)
+{
+ expression_t *function = call->function;
+ ir_node *callee = expression_to_firm(function);
+
+ assert(function->datatype->type == TYPE_FUNCTION);
+ function_type_t *function_type = (function_type_t*) function->datatype;
+
+ int n_parameters = 0;
+ call_argument_t *argument = call->arguments;
+ for( ; argument != NULL; argument = argument->next) {
+ ++n_parameters;
+ }
+
+ ir_type *ir_method_type = get_ir_type((type_t*) function_type);
+ ir_type *new_method_type = NULL;
+ if(function_type->variadic) {
+ /* we need to construct a new method type matching the call
+ * arguments... */
+ int n_res = get_method_n_ress(ir_method_type);
+ new_method_type = new_type_method(unique_ident("calltype"),
+ n_parameters, n_res);
+ set_method_calling_convention(new_method_type,
+ get_method_calling_convention(ir_method_type));
+ set_method_additional_properties(new_method_type,
+ get_method_additional_properties(ir_method_type));
+
+ for(int i = 0; i < n_res; ++i) {
+ set_method_res_type(new_method_type, i,
+ get_method_res_type(ir_method_type, i));
+ }
+ }
+ ir_node *in[n_parameters];
+
+ argument = call->arguments;
+ int n = 0;
+ for( ; argument != NULL; argument = argument->next) {
+ expression_t *expression = argument->expression;
+ ir_node *arg_node = expression_to_firm(expression);
+
+ in[n] = arg_node;
+ if(new_method_type != NULL) {
+ ir_type *irtype = get_ir_type(expression->datatype);
+ set_method_param_type(new_method_type, n, irtype);
+ }
+
+ n++;
+ }
+ assert(n == n_parameters);
+
+ if(new_method_type != NULL)
+ ir_method_type = new_method_type;
+
+ dbg_info *dbgi = get_dbg_info(&call->expression.source_position);
+ ir_node *store = get_store();
+ ir_node *node = new_d_Call(dbgi, store, callee, n_parameters, in,
+ ir_method_type);
+ ir_node *mem = new_d_Proj(dbgi, node, mode_M, pn_Call_M_regular);
+ set_store(mem);
+
+ type_t *result_type = function_type->result_type;
+ ir_node *result = NULL;
+ if(result_type != type_void) {
+ ir_mode *mode = get_ir_mode(result_type);
+ ir_node *resproj = new_d_Proj(dbgi, node, mode_T, pn_Call_T_result);
+ result = new_d_Proj(dbgi, resproj, mode, 0);
+ }
+
+ return result;
+}
+
+static ir_node *load_from_expression_addr(type_t *type, ir_node *addr,
+ dbg_info *dbgi)
+{
+ ir_mode *mode = get_ir_mode(type);
+ ir_node *memory = get_store();
+ ir_node *load = new_d_Load(dbgi, memory, addr, mode);
+ ir_node *load_mem = new_d_Proj(dbgi, load, mode_M, pn_Load_M);
+ ir_node *load_res = new_d_Proj(dbgi, load, mode, pn_Load_res);
+ set_store(load_mem);
+
+ return load_res;
+}
+
+static ir_node *expression_addr(const expression_t *expression)
+{
+ (void) expression;
+ panic("expression_addr not implemented yet");
+ return NULL;
+}
+
+static void set_value_for_expression(const expression_t *expression,
+ ir_node *value)
+{
+ if(expression->type == EXPR_REFERENCE) {
+ reference_expression_t *ref = (reference_expression_t*) expression;
+
+ declaration_t *declaration = ref->declaration;
+ assert(declaration->declaration_type != DECLARATION_TYPE_UNKNOWN);
+ if(declaration->declaration_type == DECLARATION_TYPE_LOCAL_VARIABLE) {
+ set_value(declaration->v.value_number, value);
+ return;
+ }
+ }
+ panic("set_value_for_expression not implemented yet");
+}
+
+static ir_node *create_conv(dbg_info *dbgi, ir_node *value, ir_mode *dest_mode)
+{
+ ir_mode *value_mode = get_irn_mode(value);
+
+ if(value_mode == dest_mode)
+ return value;
+
+ if(dest_mode == mode_b) {
+ ir_node *zero = new_Const(value_mode, get_mode_null(value_mode));
+ ir_node *cmp = new_d_Cmp(dbgi, value, zero);
+ ir_node *proj = new_d_Proj(dbgi, cmp, mode_b, pn_Cmp_Lg);
+ return proj;
+ }
+
+ return new_d_Conv(dbgi, value, dest_mode);
+}
+
+static ir_node *unary_expression_to_firm(const unary_expression_t *expression)
+{
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+ type_t *type = expression->expression.datatype;
+ ir_mode *mode = get_ir_mode(type);
+
+ if(expression->type == UNEXPR_TAKE_ADDRESS)
+ return expression_addr(expression->value);
+
+ const expression_t *value = expression->value;
+ ir_node *value_node = expression_to_firm(value);
+
+ switch(expression->type) {
+ case UNEXPR_NEGATE:
+ return new_d_Minus(dbgi, value_node, mode);
+ case UNEXPR_PLUS:
+ return value_node;
+ case UNEXPR_BITWISE_NEGATE:
+ return new_d_Not(dbgi, value_node, mode);
+ case UNEXPR_NOT:
+ if(get_irn_mode(value_node) != mode_b) {
+ value_node = create_conv(dbgi, value_node, mode_b);
+ }
+ value_node = new_d_Not(dbgi, value_node, mode_b);
+ if(mode != mode_b) {
+ value_node = create_conv(dbgi, value_node, mode);
+ }
+ return value_node;
+ case UNEXPR_DEREFERENCE:
+ return load_from_expression_addr(type, value_node, dbgi);
+ case UNEXPR_POSTFIX_INCREMENT: {
+ ir_node *one = new_Const(mode, get_mode_one(mode));
+ ir_node *new_value = new_d_Add(dbgi, value_node, one, mode);
+ set_value_for_expression(value, new_value);
+ return value_node;
+ }
+ case UNEXPR_POSTFIX_DECREMENT: {
+ ir_node *one = new_Const(mode, get_mode_one(mode));
+ ir_node *new_value = new_d_Sub(dbgi, value_node, one, mode);
+ set_value_for_expression(value, new_value);
+ return value_node;
+ }
+ case UNEXPR_PREFIX_INCREMENT: {
+ ir_node *one = new_Const(mode, get_mode_one(mode));
+ ir_node *new_value = new_d_Add(dbgi, value_node, one, mode);
+ set_value_for_expression(value, new_value);
+ return new_value;
+ }
+ case UNEXPR_PREFIX_DECREMENT: {
+ ir_node *one = new_Const(mode, get_mode_one(mode));
+ ir_node *new_value = new_d_Sub(dbgi, value_node, one, mode);
+ set_value_for_expression(value, new_value);
+ return new_value;
+ }
+ case UNEXPR_CAST:
+ return create_conv(dbgi, value_node, mode);
+
+ case UNEXPR_TAKE_ADDRESS:
+ case UNEXPR_INVALID:
+ break;
+ }
+ panic("invalid UNEXPR type found");
+}
+
+static long get_pnc(binary_expression_type_t type)
+{
+ switch(type) {
+ case BINEXPR_EQUAL: return pn_Cmp_Eq;
+ case BINEXPR_NOTEQUAL: return pn_Cmp_Lg;
+ case BINEXPR_LESS: return pn_Cmp_Lt;
+ case BINEXPR_LESSEQUAL: return pn_Cmp_Le;
+ case BINEXPR_GREATER: return pn_Cmp_Gt;
+ case BINEXPR_GREATEREQUAL: return pn_Cmp_Ge;
+ default:
+ break;
+ }
+ panic("trying to get pn_Cmp from non-comparison binexpr type");
+}
+
+static ir_node *binary_expression_to_firm(const binary_expression_t *expression)
+{
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+
+ binary_expression_type_t type = expression->type;
+ switch(type) {
+ case BINEXPR_EQUAL:
+ case BINEXPR_NOTEQUAL:
+ case BINEXPR_LESS:
+ case BINEXPR_LESSEQUAL:
+ case BINEXPR_GREATER:
+ case BINEXPR_GREATEREQUAL: {
+ ir_node *left = expression_to_firm(expression->left);
+ ir_node *right = expression_to_firm(expression->right);
+ ir_node *cmp = new_d_Cmp(dbgi, left, right);
+ long pnc = get_pnc(type);
+ ir_node *proj = new_d_Proj(dbgi, cmp, mode_b, pnc);
+ return proj;
+ }
+ case BINEXPR_ASSIGN: {
+ ir_node *right = expression_to_firm(expression->right);
+ set_value_for_expression(expression->left, right);
+ return right;
+ }
+ default:
+ panic("TODO binexpr type");
+ }
+}
+
+static ir_node *expression_to_firm(const expression_t *expression)