some testcases I had lying around here
[cparser] / driver / firm_cmdline.c
1 /**
2  * @file firm_cmdline.c -- Additional Firm generating backend parameters
3  *
4  * Compile when BACK_END_IS_CP_FIRM_BE is defined
5  *
6  * (C) 2005  Michael Beck  beck@ipd.info.uni-karlsruhe.de
7  *
8  * $Id$
9  */
10 #include <string.h>
11 #include "firm_cmdline.h"
12 #include <libfirm/firm.h>
13 #include <libfirm/be.h>
14
15 #ifdef _WIN32
16 #define DEFAULT_OS OS_SUPPORT_MINGW
17 #elif defined(__APPLE__)
18 #define DEFAULT_OS OS_SUPPORT_MACHO
19 #else
20 #define DEFAULT_OS OS_SUPPORT_LINUX
21 #endif
22
23 /* optimization settings */
24 struct a_firm_opt firm_opt = {
25   /* enabled         = */ TRUE,
26   /* debug_mode      = */ DBG_MODE_NONE,
27   /* const_folding   = */ TRUE,
28   /* reassoc         = */ TRUE,
29   /* cse             = */ TRUE,
30   /* control_flow    = */ TRUE,
31   /* combo           = */ TRUE,
32   /* gcse            = */ TRUE,
33   /* gvn_pre         = */ FALSE,
34   /* cond_eval       = */ FALSE,
35   /* if_conversion   = */ FALSE,
36   /* func_calls      = */ TRUE,
37   /* do_inline       = */ FALSE,
38   /* auto_inline     = */ TRUE,
39   /* tail_rec        = */ TRUE,
40   /* strength_red    = */ TRUE,
41   /* scalar_replace  = */ TRUE,
42   /* confirm         = */ TRUE,
43   /* muls            = */ TRUE,
44   /* divs            = */ TRUE,
45   /* mods            = */ TRUE,
46   /* fragile_ops     = */ TRUE,
47   /* load_store      = */ TRUE,
48   /* modes           = */ FALSE,
49   /* precise_exc     = */ FALSE,        /* never needed for C */
50   /* use_DivMod      = */ FALSE,
51   /* remove_unused   = */ TRUE,
52   /* cloning         = */ FALSE,
53   /* auto_sync       = */ TRUE,
54   /* alias_analysis  = */ TRUE,
55   /* strict_alias    = */ FALSE,
56   /* no_alias        = */ FALSE,
57   /* sync            = */ TRUE,
58   /* deconv          = */ FALSE,
59   /* cc_opt          = */ TRUE,
60   /* bool_opt        = */ FALSE,
61   /* freestanding;   = */ FALSE,
62   /* fp_model        = */ fp_model_precise,
63   /* lower_ll        = */ FALSE,
64   /* vrfy            = */ FIRM_VERIFICATION_ON,
65   /* check_all       = */ FALSE,
66   /* lower           = */ TRUE,
67   /* os_support      = */ DEFAULT_OS,
68   /* honor_restrict  = */ TRUE,
69   /* lower_bitfields = */ TRUE,
70   /* pic             = */ FALSE,
71   /* ycomp_dbg       = */ FALSE,
72   /* ycomp_host      = */ FIRM_YCOMP_DEFAULT_HOST,
73   /* ycomp_port      = */ FIRM_YCOMP_DEFAULT_PORT,
74   /* clone_threshold = */ DEFAULT_CLONE_THRESHOLD,
75   /* inline_maxsize  = */ 750,
76   /* inline_threshold= */ 0,
77   /* vrfy_edges      = */ FALSE,
78   /* grs_simd_opt    = */ 0,
79   /* grs_create_pattern = */ 0,
80   /* spare_size      = */ 128,
81 };
82
83 /* dumping options */
84 struct a_firm_dump firm_dump = {
85   /* debug_print  = */ FALSE,
86   /* all_types    = */ FALSE,
87   /* no_blocks    = */ FALSE,
88   /* extbb        = */ FALSE,
89   /* ir_graph     = */ FALSE,
90   /* all_phases   = */ FALSE,
91   /* edge_labels  = */ FALSE,
92   /* statistic    = */ STAT_NONE,
93   /* stat_pattern = */ 0,
94   /* stat_dag     = */ 0,
95   /* gen_firm_asm = */ FALSE,
96   /* filter       = */ NULL
97 };
98
99 #ifdef FIRM_EXT_GRS
100 struct a_firm_ext_grs firm_ext_grs = {
101   /* simd_opt       = */ FALSE,
102   /* create_pattern = */ FALSE
103 };
104 #endif
105
106 struct a_firm_be_opt firm_be_opt = {
107   /* selection = */ BE_FIRM_BE,
108   /* node_stat = */ 0,
109 };
110
111 #define X(a)    a, sizeof(a)-1
112
113 /** Parameter description structure */
114 static const struct params {
115   const char *option;      /**< name of the option */
116   int        opt_len;      /**< length of the option string */
117   a_byte     *flag;        /**< address of variable to set/reset */
118   a_byte     set;          /**< iff true, variable will be set, else reset */
119   const char *description; /**< description of this option */
120 } firm_options[] = {
121   /* this must be first */
122   { X("help"),                   NULL,                       0, "print FCC related help options" },
123
124   /* firm optimization options */
125   { X("pic"),                    &firm_opt.pic,              1, "firm: generate position independent code" },
126   { X("g0"),                     &firm_opt.debug_mode,       DBG_MODE_BACKSTORE, "firm: Debug Mode: use back stores" },
127   { X("g1"),                     &firm_opt.debug_mode,       DBG_MODE_FULL,      "firm: Debug Mode: no register variables" },
128   { X("no-opt"),                 NULL,                       0, "firm: disable all FIRM optimizations" },
129   { X("cse"),                    &firm_opt.cse,              1, "firm: enable common subexpression elimination" },
130   { X("no-cse"),                 &firm_opt.cse,              0, "firm: disable common subexpression elimination" },
131   { X("const-fold"),             &firm_opt.const_folding,    1, "firm: enable constant folding" },
132   { X("no-const-fold"),          &firm_opt.const_folding,    0, "firm: disable constant folding" },
133   { X("control_flow"),           &firm_opt.control_flow,     1, "firm: enable control flow optimization" },
134   { X("no-control-flow"),        &firm_opt.control_flow,     0, "firm: disable control flow optimization" },
135   { X("combo"),                  &firm_opt.combo,            1, "firm: enable combined CCE, UCE and GVN" },
136   { X("no-combo"),               &firm_opt.combo,            0, "firm: disable combined CCE, UCE and GVN" },
137   { X("gcse"),                   &firm_opt.gcse,             1, "firm: enable global common subexpression elimination" },
138   { X("no-gcse"),                &firm_opt.gcse,             0, "firm: disable global common subexpression elimination" },
139   { X("gvn-pre"),                &firm_opt.gvn_pre,          1, "firm: enable GVN partial redundancy elimination" },
140   { X("no-gvn-pre"),             &firm_opt.gvn_pre,          0, "firm: disable GVN partial redundancy elimination" },
141   { X("cond-eval"),              &firm_opt.cond_eval,        1, "firm: enable partial condition evaluation optimization" },
142   { X("no-cond-eval"),           &firm_opt.cond_eval,        0, "firm: disable partial condition evaluation optimization" },
143   { X("if-conv"),                &firm_opt.if_conversion,    1, "firm: enable if-conversion optimization" },
144   { X("no-if-conv"),             &firm_opt.if_conversion,    0, "firm: disable if-conversion optimization" },
145   { X("opt-func-call"),          &firm_opt.func_calls,       1, "firm: enable function call optimization" },
146   { X("no-opt-func-call"),       &firm_opt.func_calls,       0, "firm: disable function call optimization" },
147   { X("reassociation"),          &firm_opt.reassoc,          1, "firm: enable reassociation" },
148   { X("no-reassociation"),       &firm_opt.reassoc,          0, "firm: disable reassociation" },
149   { X("inline"),                 &firm_opt.do_inline,        1, "firm: enable FIRM inlining" },
150   { X("no-inline"),              &firm_opt.do_inline,        0, "firm: disable FIRM inlining" },
151   { X("inline-max-size=<size>"), NULL,                       0, "firm: set maximum size for function inlining" },
152   { X("inline-threshold=<size>"),NULL,                       0, "firm: set benefice threshold for function inlining" },
153   { X("tail-rec"),               &firm_opt.tail_rec,         1, "firm: enable tail-recursion optimization" },
154   { X("no-tail-rec"),            &firm_opt.tail_rec,         0, "firm: disable tail-recursion optimization" },
155   { X("strength-red"),           &firm_opt.strength_red,     1, "firm: enable strength reduction for loops" },
156   { X("no-strength-red"),        &firm_opt.strength_red,     0, "firm: disable strength reduction for loops" },
157   { X("scalar-replace"),         &firm_opt.scalar_replace,   1, "firm: enable scalar replacement" },
158   { X("no-scalar-replace"),      &firm_opt.scalar_replace,   0, "firm: disable scalar replacement" },
159   { X("confirm"),                &firm_opt.confirm,          1, "firm: enable Confirm optimization" },
160   { X("no-confirm"),             &firm_opt.confirm,          0, "firm: disable Confirm optimization" },
161   { X("opt-mul"),                &firm_opt.muls,             1, "firm: enable multiplication optimization" },
162   { X("no-opt-mul"),             &firm_opt.muls,             0, "firm: disable multiplication optimization" },
163   { X("opt-div"),                &firm_opt.divs,             1, "firm: enable division optimization" },
164   { X("no-opt-div"),             &firm_opt.divs,             0, "firm: disable division optimization" },
165   { X("opt-mod"),                &firm_opt.mods,             1, "firm: enable remainder optimization" },
166   { X("no-opt-mod"),             &firm_opt.mods,             0, "firm: disable remainder optimization" },
167   { X("opt-fragile-ops"),        &firm_opt.fragile_ops,      1, "firm: enable fragile ops optimization" },
168   { X("no-opt-fragile-ops"),     &firm_opt.fragile_ops,      0, "firm: disable fragile ops optimization" },
169   { X("opt-load-store"),         &firm_opt.load_store,       1, "firm: enable load store optimization" },
170   { X("no-opt-load-store"),      &firm_opt.load_store,       0, "firm: disable load store optimization" },
171   { X("opt-modes"),              &firm_opt.modes,            1, "firm: optimize integer modes" },
172   { X("no-opt-modes"),           &firm_opt.modes,            0, "firm: disable integer modes optimization" },
173   { X("sync"),                   &firm_opt.auto_sync,        1, "firm: automatically create Sync nodes" },
174   { X("no-sync"),                &firm_opt.auto_sync,        0, "firm: do not create Sync nodes" },
175   { X("opt-alias"),              &firm_opt.alias_analysis,   1, "firm: enable alias analysis" },
176   { X("no-opt-alias"),           &firm_opt.alias_analysis,   0, "firm: disable alias analysis" },
177   { X("alias"),                  &firm_opt.no_alias,         0, "firm: aliasing occurs" },
178   { X("no-alias"),               &firm_opt.no_alias,         1, "firm: no aliasing occurs" },
179   { X("strict-aliasing"),        &firm_opt.strict_alias,     1, "firm: strict alias rules" },
180   { X("no-strict-aliasing"),     &firm_opt.strict_alias,     0, "firm: strict alias rules" },
181   { X("opt-proc-clone"),         &firm_opt.cloning,          1, "firm: enable procedure cloning" },
182   { X("no-opt-proc-clone"),      &firm_opt.cloning,          0, "firm: disable procedure cloning" },
183   { X("clone-threshold=<value>"),NULL,                       0, "firm: set clone threshold to <value>" },
184   { X("DivMod"),                 &firm_opt.use_DivMod,       1, "firm: use DivMod nodes" },
185   { X("no-DivMod"),              &firm_opt.use_DivMod,       0, "firm: don't use DivMod nodes" },
186   { X("precise-except"),         &firm_opt.precise_exc,      1, "firm: precise exception context" },
187   { X("no-precise-except"),      &firm_opt.precise_exc,      0, "firm: no precise exception context" },
188   { X("remove-unused"),          &firm_opt.remove_unused,    1, "firm: remove unused functions" },
189   { X("no-remove-unused"),       &firm_opt.remove_unused,    0, "firm: dont't remove unused functions" },
190   { X("fp-precise"),             &firm_opt.fp_model,         fp_model_precise, "firm: precise fp model" },
191   { X("fp-fast"),                &firm_opt.fp_model,         fp_model_fast,    "firm: fast fp model" },
192   { X("fp-strict"),              &firm_opt.fp_model,         fp_model_strict,  "firm: strict fp model" },
193   { X("sync"),                   &firm_opt.sync,             1, "firm: use Syncs to remove unnecessary memory dependencies" },
194   { X("no-sync"),                &firm_opt.sync,             0, "firm: do not use Syncs to remove unnecessary memory dependencies" },
195   { X("deconv"),                 &firm_opt.deconv,           1, "firm: enable the conv node optimization" },
196   { X("no-deconv"),              &firm_opt.deconv,           0, "firm: disable the conv node optimization" },
197   { X("opt-cc"),                 &firm_opt.cc_opt,           1, "firm: enable calling conventions optimization" },
198   { X("no-opt-cc"),              &firm_opt.cc_opt,           0, "firm: disable calling conventions optimization" },
199   { X("bool"),                   &firm_opt.bool_opt,         1, "firm: enable bool simplification optimization" },
200   { X("no-bool"),                &firm_opt.bool_opt,         0, "firm: disable bool simplification optimization" },
201   { X("freestanding"),           &firm_opt.freestanding,     1, "firm: freestanding environment" },
202   { X("hosted"),                 &firm_opt.freestanding,     0, "firm: hosted environment" },
203
204   /* other firm regarding options */
205   { X("restrict"),               &firm_opt.honor_restrict,   1, "firm: honor restrict keyword" },
206   { X("no-restrict"),            &firm_opt.honor_restrict,   1, "firm: restrict keyword is meaningless" },
207   { X("no-lower"),               &firm_opt.lower,            0, "firm: disable lowering" },
208   { X("vrfy-off"),               &firm_opt.vrfy,             FIRM_VERIFICATION_OFF, "firm: disable node verification" },
209   { X("vrfy-on"),                &firm_opt.vrfy,             FIRM_VERIFICATION_ON, "firm: enable node verification" },
210   { X("vrfy-report"),            &firm_opt.vrfy,             FIRM_VERIFICATION_REPORT, "firm: node verification, report only" },
211   { X("check-all"),              &firm_opt.check_all,        1, "firm: enable checking all Firm phases" },
212   { X("no-check-all"),           &firm_opt.check_all,        0, "firm: disable checking all Firm phases" },
213   { X("vrfy-edges-on"),          &firm_opt.vrfy_edges,       1, "firm: enable out edge verification" },
214   { X("vrfy-edges-off"),         &firm_opt.vrfy_edges,       0, "firm: disable out edge verification" },
215
216   /* dumping */
217 #if defined(_DEBUG) || defined(FIRM_DEBUG)
218   { X("debug"),                  &firm_dump.debug_print,     1, "firm: enable debug output" },
219 #endif
220
221   { X("dump-ir"),                &firm_dump.ir_graph,        1, "firm: dump IR graph" },
222   { X("dump-all-types"),         &firm_dump.all_types,       1, "firm: dump graph of all types" },
223   { X("dump-no-blocks"),         &firm_dump.no_blocks,       1, "firm: dump non-blocked graph" },
224   { X("dump-extbb"),             &firm_dump.extbb,           1, "firm: dump extended basic blocks" },
225   { X("dump-all-phases"),        &firm_dump.all_phases,      1, "firm: dump graphs for all optimization phases" },
226   { X("dump-edge-labels"),       &firm_dump.edge_labels,     1, "firm: dump edge labels" },
227
228   /* code generation */
229   { X("no-codegen"),             &firm_be_opt.selection,     BE_NONE, "cg: disable code generator" },
230
231 #ifdef FIRM_EXT_GRS
232   { X("grs-simd-opt"),           &firm_ext_grs.simd_opt,                1, "firm: do simd optimization" },
233   { X("grs-create-pattern"),     &firm_ext_grs.create_pattern,  1, "firm: create patterns for simd optimization" },
234   { X("no-grs-simd-opt"),        &firm_ext_grs.simd_opt,                0, "firm: do simd optimization" },
235   { X("no-grs-create-pattern"),  &firm_ext_grs.create_pattern,  0, "firm: create patterns for simd optimization" },
236 #endif
237
238 #ifdef FIRM_BACKEND
239   { X("be-firm"),                &firm_be_opt.selection,     BE_FIRM_BE, "backend: firm backend facility" },
240 #endif /* FIRM_BACKEND */
241 #ifdef FIRM2C_BACKEND
242   { X("be-firm2c"),              &firm_be_opt.selection,     BE_FIRM2C, "backend: firm2C" },
243 #endif /* FIRM2C_BACKEND */
244
245   /* misc */
246   { X("stat-before-opt"),        &firm_dump.statistic,       STAT_BEFORE_OPT,  "misc: Firm statistic output before optimizations" },
247   { X("stat-after-opt"),         &firm_dump.statistic,       STAT_AFTER_OPT,   "misc: Firm statistic output after optimizations" },
248   { X("stat-after-lower"),       &firm_dump.statistic,       STAT_AFTER_LOWER, "misc: Firm statistic output after lowering" },
249   { X("stat-final-ir"),          &firm_dump.statistic,       STAT_FINAL_IR,    "misc: Firm statistic after final optimization" },
250   { X("stat-final"),             &firm_dump.statistic,       STAT_FINAL,       "misc: Firm statistic after code generation" },
251   { X("stat-pattern"),           &firm_dump.stat_pattern,    1, "misc: Firm statistic calculates most used pattern" },
252   { X("stat-dag"),               &firm_dump.stat_dag,        1, "misc: Firm calculates DAG statistics" },
253   { X("firm-asm"),               &firm_dump.gen_firm_asm,    1, "misc: output Firm assembler" },
254   { X("win32"),                  &firm_opt.os_support,       OS_SUPPORT_MINGW, "misc: generate MinGW Win32 code" },
255   { X("mac"),                    &firm_opt.os_support,       OS_SUPPORT_MACHO, "misc: generate MacOS code" },
256   { X("linux"),                  &firm_opt.os_support,       OS_SUPPORT_LINUX, "misc: generate Linux-ELF code" },
257   { X("ycomp"),                  &firm_opt.ycomp_dbg,        1, "misc: enable yComp debugger extension" },
258   { X("ycomp-host=<hostname>"),  NULL,                       0, "misc: yComp host" },
259   { X("ycomp-port=<port>"),      NULL,                       0, "misc: yComp port" },
260
261   /* string options */
262   { X("dump-filter=<string>"),   NULL,                       0, "misc: set dumper filter" },
263 };
264
265 #undef X
266
267 /** A strdup replacement */
268 static char *StrDup(const char *s) {
269   int   l = strlen(s);
270   char *r = malloc(l+1);
271
272   if (r != NULL)
273     memcpy(r, s, l+1);
274   return r;
275 }
276
277 /**
278  * Set a dumper filter.
279  */
280 static void set_dump_filter(const char *filter)
281 {
282   firm_dump.filter = StrDup(filter);
283 }  /* set_dump_filter */
284
285 /**
286  * Set ycomp host
287  */
288 static void set_ycomp_host(const char *host)
289 {
290   firm_opt.ycomp_host = StrDup(host);
291 }  /* set_ycomp_host */
292
293 /** Disable all optimizations. */
294 static void disable_opts(void) {
295   /* firm_opt.const_folding */
296   firm_opt.reassoc         = FALSE;
297   firm_opt.cse             = FALSE;
298   /* firm_opt.control_flow */
299   firm_opt.gcse            = FALSE;
300   firm_opt.gvn_pre         = FALSE;
301   firm_opt.cond_eval       = FALSE;
302   firm_opt.if_conversion   = FALSE;
303   firm_opt.func_calls      = FALSE;
304   firm_opt.do_inline       = FALSE;
305   firm_opt.auto_inline     = FALSE;
306   firm_opt.tail_rec        = FALSE;
307   firm_opt.strength_red    = FALSE;
308   firm_opt.scalar_replace  = FALSE;
309   firm_opt.confirm         = FALSE;
310   firm_opt.muls            = FALSE;
311   firm_opt.divs            = FALSE;
312   firm_opt.mods            = FALSE;
313   firm_opt.fragile_ops     = FALSE;
314   firm_opt.load_store      = FALSE;
315   firm_opt.remove_unused   = FALSE;
316   /* firm_opt.jmp_tbls */
317   firm_opt.cloning         = FALSE;
318   /* firm_opt.auto_sync */
319   firm_opt.alias_analysis  = FALSE;
320   firm_opt.strict_alias    = FALSE;
321   firm_opt.no_alias        = FALSE;
322   firm_opt.sync            = FALSE;
323   firm_opt.deconv          = FALSE;
324   firm_opt.cc_opt          = FALSE;
325   firm_opt.bool_opt        = FALSE;
326   firm_opt.freestanding    = TRUE;
327 }  /* disable_opts */
328
329 /**
330  * Handles a firm option.
331  */
332 int firm_option(const char *opt)
333 {
334   int i, len    = strlen(opt);
335   const char *p = opt;
336   int res;
337
338   if (strncmp("dump-filter=", opt, 12) == 0) {
339     opt = &opt[12];
340     set_dump_filter(opt);
341     return 1;
342   }
343   else if (strncmp("clone-threshold=", opt, 16) == 0) {
344     sscanf(&opt[16], "%d", &firm_opt.clone_threshold);
345     firm_opt.cloning = TRUE;
346     return 1;
347   }
348   else if (strncmp("inline-max-size=", opt, 16) == 0) {
349     sscanf(&opt[16], "%u", &firm_opt.inline_maxsize);
350     return 1;
351   }
352   else if (strncmp("inline-threshold=", opt, 17) == 0) {
353     sscanf(&opt[17], "%u", &firm_opt.inline_threshold);
354     return 1;
355   }
356   else if (strncmp("ycomp-host=", opt, 11) == 0) {
357     opt = &opt[11];
358     set_ycomp_host(opt);
359     return 1;
360   }
361   else if (strncmp("ycomp-port=", opt, 11) == 0) {
362     sscanf(&opt[11], "%d", &firm_opt.ycomp_port);
363     return 1;
364   }
365   else if (strcmp("no-opt", opt) == 0) {
366     disable_opts();
367     return 1;
368   }
369
370   for (i = sizeof(firm_options) / sizeof(firm_options[0]) - 1; i >= 0; --i) {
371     if (len == firm_options[i].opt_len && strncmp(p, firm_options[i].option, len) == 0) {
372       if (!firm_options[i].flag) {
373         /* help option */
374         for (i = 0; i < (int) (sizeof(firm_options)/sizeof(firm_options[0])); ++i) {
375           printf("-f %-20s %s\n", firm_options[i].option,
376                  firm_options[i].description);
377         }
378         return -1;
379       }
380       /* statistic options do accumulate */
381       if (firm_options[i].flag == &firm_dump.statistic)
382         *firm_options[i].flag = (a_byte) (*firm_options[i].flag | firm_options[i].set);
383       else
384         *firm_options[i].flag = firm_options[i].set;
385
386       if (firm_options[i].flag == &firm_opt.debug_mode && firm_opt.debug_mode > DBG_MODE_NONE) {
387         if (firm_opt.debug_mode == DBG_MODE_FULL)
388           disable_opts();
389         res = 1;
390         res &= firm_be_option("omitfp=0");
391         res &= firm_be_option("stabs");
392         return res;
393       }
394       break;
395     }
396   }
397
398   if (i < 0)
399     return 0;
400   return 1;
401 }  /* firm_option */
402
403 /**
404  * Handles a firm backend option.
405  *
406  * The options are here only checked for validity and later transmitted
407  * to the firm backend (in the hope they do not fail ...)
408  */
409 int firm_be_option(const char *opt) {
410 #ifdef FIRM_BACKEND
411   return be_parse_arg(opt);
412 #else
413   return 0;
414 #endif /* FIRM_BACKEND */
415 }  /* firm_be_option */
416
417 /**
418  * prints the firm version number
419  */
420 void print_firm_version(FILE *f) {
421   firm_version_t version;
422
423   firm_get_version(&version);
424
425   fprintf(f, "Firm C-Compiler using libFirm (%u.%u", version.major, version.minor);
426   if (version.revision[0] != 0) {
427         fputc(' ', f);
428     fputs(version.revision, f);
429   }
430    if(version.build[0] != 0) {
431         fputc(' ', f);
432     fputs(version.build, f);
433   }
434   fprintf(f, "}\n"
435                      "(C) 2005-2008 Michael Beck\n"
436              "(C) 1995-2008 University of Karlsruhe\n"
437              "Using ");
438 }  /* print_firm_version */