+static ir_mode *get_ir_mode_arithmetic(type_t *type)
+{
+ ir_mode *mode = get_ir_mode_storage(type);
+ if (mode_is_float(mode) && mode_float_arithmetic != NULL) {
+ return mode_float_arithmetic;
+ }
+
+ return mode;
+}
+
+/** Names of the runtime functions. */
+static const struct {
+ int id; /**< the rts id */
+ int n_res; /**< number of return values */
+ const char *name; /**< the name of the rts function */
+ int n_params; /**< number of parameters */
+ unsigned flags; /**< language flags */
+} rts_data[] = {
+ { rts_debugbreak, 0, "__debugbreak", 0, _MS },
+ { rts_abort, 0, "abort", 0, _C89 },
+ { rts_alloca, 1, "alloca", 1, _ALL },
+ { rts_abs, 1, "abs", 1, _C89 },
+ { rts_labs, 1, "labs", 1, _C89 },
+ { rts_llabs, 1, "llabs", 1, _C99 },
+ { rts_imaxabs, 1, "imaxabs", 1, _C99 },
+
+ { rts_fabs, 1, "fabs", 1, _C89 },
+ { rts_sqrt, 1, "sqrt", 1, _C89 },
+ { rts_cbrt, 1, "cbrt", 1, _C99 },
+ { rts_exp, 1, "exp", 1, _C89 },
+ { rts_exp2, 1, "exp2", 1, _C89 },
+ { rts_exp10, 1, "exp10", 1, _GNUC },
+ { rts_log, 1, "log", 1, _C89 },
+ { rts_log2, 1, "log2", 1, _C89 },
+ { rts_log10, 1, "log10", 1, _C89 },
+ { rts_pow, 1, "pow", 2, _C89 },
+ { rts_sin, 1, "sin", 1, _C89 },
+ { rts_cos, 1, "cos", 1, _C89 },
+ { rts_tan, 1, "tan", 1, _C89 },
+ { rts_asin, 1, "asin", 1, _C89 },
+ { rts_acos, 1, "acos", 1, _C89 },
+ { rts_atan, 1, "atan", 1, _C89 },
+ { rts_sinh, 1, "sinh", 1, _C89 },
+ { rts_cosh, 1, "cosh", 1, _C89 },
+ { rts_tanh, 1, "tanh", 1, _C89 },
+
+ { rts_fabsf, 1, "fabsf", 1, _C99 },
+ { rts_sqrtf, 1, "sqrtf", 1, _C99 },
+ { rts_cbrtf, 1, "cbrtf", 1, _C99 },
+ { rts_expf, 1, "expf", 1, _C99 },
+ { rts_exp2f, 1, "exp2f", 1, _C99 },
+ { rts_exp10f, 1, "exp10f", 1, _GNUC },
+ { rts_logf, 1, "logf", 1, _C99 },
+ { rts_log2f, 1, "log2f", 1, _C99 },
+ { rts_log10f, 1, "log10f", 1, _C99 },
+ { rts_powf, 1, "powf", 2, _C99 },
+ { rts_sinf, 1, "sinf", 1, _C99 },
+ { rts_cosf, 1, "cosf", 1, _C99 },
+ { rts_tanf, 1, "tanf", 1, _C99 },
+ { rts_asinf, 1, "asinf", 1, _C99 },
+ { rts_acosf, 1, "acosf", 1, _C99 },
+ { rts_atanf, 1, "atanf", 1, _C99 },
+ { rts_sinhf, 1, "sinhf", 1, _C99 },
+ { rts_coshf, 1, "coshf", 1, _C99 },
+ { rts_tanhf, 1, "tanhf", 1, _C99 },
+
+ { rts_fabsl, 1, "fabsl", 1, _C99 },
+ { rts_sqrtl, 1, "sqrtl", 1, _C99 },
+ { rts_cbrtl, 1, "cbrtl", 1, _C99 },
+ { rts_expl, 1, "expl", 1, _C99 },
+ { rts_exp2l, 1, "exp2l", 1, _C99 },
+ { rts_exp10l, 1, "exp10l", 1, _GNUC },
+ { rts_logl, 1, "logl", 1, _C99 },
+ { rts_log2l, 1, "log2l", 1, _C99 },
+ { rts_log10l, 1, "log10l", 1, _C99 },
+ { rts_powl, 1, "powl", 2, _C99 },
+ { rts_sinl, 1, "sinl", 1, _C99 },
+ { rts_cosl, 1, "cosl", 1, _C99 },
+ { rts_tanl, 1, "tanl", 1, _C99 },
+ { rts_asinl, 1, "asinl", 1, _C99 },
+ { rts_acosl, 1, "acosl", 1, _C99 },
+ { rts_atanl, 1, "atanl", 1, _C99 },
+ { rts_sinhl, 1, "sinhl", 1, _C99 },
+ { rts_coshl, 1, "coshl", 1, _C99 },
+ { rts_tanhl, 1, "tanhl", 1, _C99 },
+
+ { rts_strcmp, 1, "strcmp", 2, _C89 },
+ { rts_strncmp, 1, "strncmp", 3, _C89 },
+ { rts_strcpy, 1, "strcpy", 2, _C89 },
+ { rts_strlen, 1, "strlen", 1, _C89 },
+ { rts_memcpy, 1, "memcpy", 3, _C89 }, /* HMM, man say its C99 */
+ { rts_mempcpy, 1, "mempcpy", 3, _GNUC },
+ { rts_memmove, 1, "memmove", 3, _C89 }, /* HMM, man say its C99 */
+ { rts_memset, 1, "memset", 3, _C89 }, /* HMM, man say its C99 */
+ { rts_memcmp, 1, "memcmp", 3, _C89 }, /* HMM, man say its C99 */
+};
+
+static ident *rts_idents[lengthof(rts_data)];
+
+static ident* (*create_ld_ident)(entity_t*) = create_name_linux_elf;
+
+/**
+ * Handle GNU attributes for entities
+ *
+ * @param ent the entity
+ * @param decl the routine declaration
+ */
+static void handle_decl_modifiers(ir_entity *irentity, entity_t *entity)
+{
+ assert(is_declaration(entity));
+ decl_modifiers_t modifiers = entity->declaration.modifiers;
+ if (modifiers & DM_PURE) {
+ /* TRUE if the declaration includes the GNU
+ __attribute__((pure)) specifier. */
+ set_entity_additional_property(irentity, mtp_property_pure);
+ }
+ if (modifiers & DM_CONST) {
+ set_entity_additional_property(irentity, mtp_property_const);
+ have_const_functions = true;
+ }
+ if (modifiers & DM_USED) {
+ /* TRUE if the declaration includes the GNU
+ __attribute__((used)) specifier. */
+ set_entity_stickyness(irentity, stickyness_sticky);
+ }
+}
+
+static bool is_main(entity_t *entity)
+{
+ static symbol_t *sym_main = NULL;
+ if (sym_main == NULL) {
+ sym_main = symbol_table_insert("main");
+ }
+
+ if (entity->base.symbol != sym_main)
+ return false;
+ /* must be in outermost scope */
+ if (entity->base.parent_scope != ¤t_translation_unit->scope)
+ return false;
+
+ return true;
+}
+
+/**
+ * Creates an entity representing a function.
+ *
+ * @param declaration the function declaration
+ * @param owner_type the owner type of this function, NULL
+ * for global functions
+ */
+static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)