- refactor emitter next/prev block handling a bit
[libfirm] / ir / be / bemain.c
index 42eac6d..544a525 100644 (file)
@@ -89,6 +89,7 @@ static be_options_t be_options = {
        BE_TIME_OFF,                       /* no timing */
        0,                                 /* no opt profile */
        0,                                 /* try to omit frame pointer */
+       0,                                 /* try to omit leaf frame pointer */
        0,                                 /* create PIC code */
        0,                                 /* create gprof compatible profiling code */
        BE_VRFY_WARN,                      /* verification level: warn */
@@ -150,19 +151,20 @@ static lc_opt_enum_int_var_t sched_var = {
 };
 
 static const lc_opt_table_entry_t be_main_options[] = {
-       LC_OPT_ENT_STR      ("config",   "read another config file containing backend options", config_file, sizeof(config_file)),
-       LC_OPT_ENT_ENUM_MASK("dump",     "dump irg on several occasions",                       &dump_var),
-       LC_OPT_ENT_BOOL     ("omitfp",   "omit frame pointer",                                  &be_options.omit_fp),
-       LC_OPT_ENT_BOOL     ("pic",      "create PIC code",                                     &be_options.pic),
-       LC_OPT_ENT_BOOL     ("gprof",    "create gprof profiling code",                         &be_options.gprof),
-       LC_OPT_ENT_ENUM_PTR ("vrfy",     "verify the backend irg",                              &vrfy_var),
-       LC_OPT_ENT_BOOL     ("time",     "get backend timing statistics",                       &be_options.timing),
-       LC_OPT_ENT_BOOL     ("profile",  "instrument the code for execution count profiling",   &be_options.opt_profile),
-       LC_OPT_ENT_ENUM_PTR ("sched",    "select a scheduler",                                  &sched_var),
-       LC_OPT_ENT_STR      ("os",       "specify target operating system",                     &be_options.target_os, sizeof(be_options.target_os)),
+       LC_OPT_ENT_STR      ("config",     "read another config file containing backend options", config_file, sizeof(config_file)),
+       LC_OPT_ENT_ENUM_MASK("dump",       "dump irg on several occasions",                       &dump_var),
+       LC_OPT_ENT_BOOL     ("omitfp",     "omit frame pointer",                                  &be_options.omit_fp),
+       LC_OPT_ENT_BOOL     ("omitleaffp", "omit frame pointer in leaf routines",                 &be_options.omit_leaf_fp),
+       LC_OPT_ENT_BOOL     ("pic",        "create PIC code",                                     &be_options.pic),
+       LC_OPT_ENT_BOOL     ("gprof",      "create gprof profiling code",                         &be_options.gprof),
+       LC_OPT_ENT_ENUM_PTR ("vrfy",       "verify the backend irg",                              &vrfy_var),
+       LC_OPT_ENT_BOOL     ("time",       "get backend timing statistics",                       &be_options.timing),
+       LC_OPT_ENT_BOOL     ("profile",    "instrument the code for execution count profiling",   &be_options.opt_profile),
+       LC_OPT_ENT_ENUM_PTR ("sched",      "select a scheduler",                                  &sched_var),
+       LC_OPT_ENT_STR      ("os",         "specify target operating system",                     &be_options.target_os, sizeof(be_options.target_os)),
 #ifdef FIRM_STATISTICS
-       LC_OPT_ENT_BOOL     ("statev",   "dump statistic events",                               &be_options.statev),
-       LC_OPT_ENT_STR      ("filtev",   "filter for stat events (regex if support is active",  &be_options.filtev, sizeof(be_options.filtev)),
+       LC_OPT_ENT_BOOL     ("statev",     "dump statistic events",                               &be_options.statev),
+       LC_OPT_ENT_STR      ("filtev",     "filter for stat events (regex if support is active",  &be_options.filtev, sizeof(be_options.filtev)),
 #endif
 
 #ifdef WITH_ILP
@@ -174,6 +176,132 @@ static const lc_opt_table_entry_t be_main_options[] = {
 
 static be_module_list_entry_t *isa_ifs = NULL;
 
+
+unsigned short asm_constraint_flags[256];
+
+void be_init_default_asm_constraint_flags(void)
+{
+       asm_constraint_flags['?'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
+       asm_constraint_flags['!'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
+       asm_constraint_flags['&'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT
+               | ASM_CONSTRAINT_FLAG_MODIFIER_EARLYCLOBBER;
+       asm_constraint_flags['%'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT
+               | ASM_CONSTRAINT_FLAG_MODIFIER_COMMUTATIVE;
+       asm_constraint_flags['!'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
+
+       asm_constraint_flags['='] = ASM_CONSTRAINT_FLAG_MODIFIER_WRITE
+               | ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ;
+       asm_constraint_flags['+'] = ASM_CONSTRAINT_FLAG_MODIFIER_READ
+               | ASM_CONSTRAINT_FLAG_MODIFIER_WRITE;
+
+       asm_constraint_flags['i'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['s'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['E'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['F'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['G'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['H'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['I'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['J'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['K'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['L'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['M'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['N'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['O'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+       asm_constraint_flags['P'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+
+       asm_constraint_flags['m'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
+       asm_constraint_flags['o'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
+       asm_constraint_flags['V'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
+       asm_constraint_flags['<'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
+       asm_constraint_flags['>'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
+
+       asm_constraint_flags['p'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
+       asm_constraint_flags['0'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
+       asm_constraint_flags['1'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
+       asm_constraint_flags['2'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
+       asm_constraint_flags['3'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
+       asm_constraint_flags['4'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
+       asm_constraint_flags['5'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
+       asm_constraint_flags['6'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
+       asm_constraint_flags['7'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
+       asm_constraint_flags['8'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
+       asm_constraint_flags['9'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
+
+       asm_constraint_flags['X'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER
+               | ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP
+               | ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
+
+       /* these should have been catched by the parsing code already */
+       asm_constraint_flags['#']  = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
+       asm_constraint_flags['*']  = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
+       asm_constraint_flags[' ']  = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
+       asm_constraint_flags['\t'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
+       asm_constraint_flags['\n'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
+       asm_constraint_flags['\r'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
+}
+
+asm_constraint_flags_t be_parse_asm_constraints(const char *constraint)
+{
+       asm_constraint_flags_t  flags = 0;
+       const char             *c;
+       asm_constraint_flags_t  tflags;
+
+       for (c = constraint; *c != '\0'; ++c) {
+               switch (*c) {
+               case '#':
+                       /* 'comment' stuff */
+                       while(*c != 0 && *c != ',')
+                               ++c;
+                       break;
+               case '*':
+                       /* 'comment' character */
+                       ++c;
+                       break;
+               case ' ':
+               case '\t':
+               case '\n':
+               case '\r':
+                       break;
+               default:
+                       tflags = asm_constraint_flags[(int) *c];
+                       if (tflags != 0) {
+                               flags |= tflags;
+                       } else {
+                               flags |= isa_if->parse_asm_constraint(isa_if, &c);
+                       }
+                       break;
+               }
+       }
+
+       if ( ((flags & ASM_CONSTRAINT_FLAG_MODIFIER_WRITE)
+                       && (flags & ASM_CONSTRAINT_FLAG_MODIFIER_NO_WRITE))
+               || ((flags & ASM_CONSTRAINT_FLAG_MODIFIER_READ
+                       && (flags & ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ)))) {
+               flags |= ASM_CONSTRAINT_FLAG_INVALID;
+       }
+       if (! (flags & (ASM_CONSTRAINT_FLAG_MODIFIER_READ
+                                       | ASM_CONSTRAINT_FLAG_MODIFIER_WRITE
+                                       | ASM_CONSTRAINT_FLAG_MODIFIER_NO_WRITE
+                                       | ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ))) {
+               flags |= ASM_CONSTRAINT_FLAG_MODIFIER_READ;
+       }
+
+       return flags;
+}
+
+bool be_is_valid_clobber(const char *clobber)
+{
+       /* memory is a valid clobber. (the frontend has to detect this case too,
+        * because it has to add memory edges to the asm) */
+       if (strcmp(clobber, "memory") == 0)
+               return true;
+       /* cc (condition code) is always valid */
+       if (strcmp(clobber, "cc") == 0)
+               return true;
+
+       return isa_if->is_valid_clobber(isa_if, clobber);
+}
+
 void be_register_isa_if(const char *name, const arch_isa_if_t *isa)
 {
        if (isa_if == NULL)
@@ -233,12 +361,16 @@ static void be_sched_vrfy(be_irg_t *birg, int vrfy_opt) {
        }
 }
 
-/* Initialize the Firm backend. Must be run BEFORE init_firm()! */
-const backend_params *be_init(void)
+/* Initialize the Firm backend. Must be run first in init_firm()! */
+void firm_be_init(void)
 {
        be_opt_register();
        be_init_modules();
+}
 
+/* Returns the backend parameter */
+const backend_params *be_get_backend_param(void)
+{
        if (isa_if->get_params)
                return isa_if->get_params();
        return &be_params;
@@ -263,6 +395,7 @@ static be_main_env_t *be_init_env(be_main_env_t *env, FILE *file_handle)
        remove_irp_type(env->pic_symbols_type);
        set_class_final(env->pic_trampolines_type, 1);
 
+       memset(asm_constraint_flags, 0, sizeof(asm_constraint_flags));
        env->arch_env = arch_env_init(isa_if, file_handle, env);
 
        be_phi_handler_new(env);
@@ -330,7 +463,7 @@ static void initialize_birg(be_irg_t *birg, ir_graph *irg, be_main_env_t *env)
        normalize_n_returns(irg);
 
        /* Remove critical edges */
-       remove_critical_cf_edges(irg);
+       remove_critical_cf_edges_ex(irg, /*ignore_exception_edges=*/0);
 
        /* Ensure, that the ir_edges are computed. */
        edges_assure(irg);