Merge branch 'master' into verilog-ams
[sverilog.git] / main.cc
blob640fcf4d3ac296ddcd1599e36fb7549890e0e922
2 const char COPYRIGHT[] =
3 "Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)";
5 /*
6 * This source code is free software; you can redistribute it
7 * and/or modify it in source code form under the terms of the GNU
8 * General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
22 # include "config.h"
24 const char NOTICE[] =
25 " This program is free software; you can redistribute it and/or modify\n"
26 " it under the terms of the GNU General Public License as published by\n"
27 " the Free Software Foundation; either version 2 of the License, or\n"
28 " (at your option) any later version.\n"
29 "\n"
30 " This program is distributed in the hope that it will be useful,\n"
31 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
32 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
33 " GNU General Public License for more details.\n"
34 "\n"
35 " You should have received a copy of the GNU General Public License\n"
36 " along with this program; if not, write to the Free Software\n"
37 " Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
40 # include <stdio.h>
41 # include <iostream>
42 # include <fstream>
43 # include <queue>
44 # include <cstring>
45 # include <list>
46 # include <map>
47 # include <unistd.h>
48 # include <stdlib.h>
49 #if defined(HAVE_TIMES)
50 # include <sys/times.h>
51 #endif
52 #if defined(HAVE_GETOPT_H)
53 # include <getopt.h>
54 #endif
55 # include "pform.h"
56 # include "parse_api.h"
57 # include "netlist.h"
58 # include "target.h"
59 # include "compiler.h"
60 # include "discipline.h"
62 #if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
63 extern "C" int getopt(int argc, char*argv[], const char*fmt);
64 extern "C" int optind;
65 extern "C" const char*optarg;
66 #endif
68 #if defined(__CYGWIN32__) && !defined(HAVE_GETOPT_H)
69 extern "C" int getopt(int argc, char*argv[], const char*fmt);
70 extern "C" int optind;
71 extern "C" const char*optarg;
72 #endif
74 /* Count errors detected in flag processing. */
75 unsigned flag_errors = 0;
77 const char VERSION[] = "$Name: $";
79 const char*basedir = ".";
81 const char*target = "null";
84 * These are the language support control flags. These support which
85 * language features (the generation) to support. The generation_flag
86 * is a major mode, and the gn_* flags control specific sub-features.
88 generation_t generation_flag = GN_DEFAULT;
89 bool gn_icarus_misc_flag = true;
90 bool gn_cadence_types_flag = true;
91 bool gn_specify_blocks_flag = true;
92 bool gn_io_range_error_flag = true;
93 bool gn_verilog_ams_flag = false;
95 map<string,const char*> flags;
96 char*vpi_module_list = 0;
98 map<perm_string,unsigned> missing_modules;
99 map<perm_string,bool> library_file_map;
101 list<const char*> library_suff;
103 list<perm_string> roots;
105 char*ivlpp_string = 0;
107 char* depfile_name = NULL;
108 FILE *depend_file = NULL;
111 * These are the warning enable flags.
113 bool warn_implicit = false;
114 bool warn_timescale = false;
115 bool warn_portbinding = false;
116 bool warn_inf_loop = false;
118 bool error_implicit = false;
121 * Debug message class flags.
123 bool debug_scopes = false;
124 bool debug_eval_tree = false;
125 bool debug_elaborate = false;
126 bool debug_synth2 = false;
127 bool debug_optimizer = false;
130 * Verbose messages enabled.
132 bool verbose_flag = false;
134 unsigned integer_width = 32;
137 * Keep a heap of identifier strings that I encounter. This is a more
138 * efficient way to allocate those strings.
140 StringHeapLex lex_strings;
142 StringHeapLex filename_strings;
145 * In library searches, Windows file names are never case sensitive.
147 #if defined(__MINGW32__)
148 const bool CASE_SENSITIVE = false;
149 #else
150 const bool CASE_SENSITIVE = true;
151 #endif
154 * Are we doing synthesis?
156 bool synthesis = false;
158 extern void cprop(Design*des);
159 extern void synth(Design*des);
160 extern void synth2(Design*des);
161 extern void syn_rules(Design*des);
162 extern void nodangle(Design*des);
163 #ifdef WITH_T_XNF
164 extern void xnfio(Design*des);
165 #endif
167 typedef void (*net_func)(Design*);
168 static struct net_func_map {
169 const char*name;
170 void (*func)(Design*);
171 } func_table[] = {
172 { "cprop", &cprop },
173 { "nodangle",&nodangle },
174 { "synth", &synth },
175 { "synth2", &synth2 },
176 { "syn-rules", &syn_rules },
177 #ifdef WITH_T_XNF
178 { "xnfio", &xnfio },
179 #endif
180 { 0, 0 }
183 queue<net_func> net_func_queue;
185 net_func name_to_net_func(const string&name)
187 for (unsigned idx = 0 ; func_table[idx].name ; idx += 1)
188 if (name == func_table[idx].name)
189 return func_table[idx].func;
191 return 0;
194 const char *net_func_to_name(const net_func func)
196 for (unsigned idx = 0 ; func_table[idx].name ; idx += 1)
197 if (func == func_table[idx].func)
198 return func_table[idx].name;
200 return "This cannot happen";
203 static void process_generation_flag(const char*gen)
205 if (strcmp(gen,"1") == 0) { // FIXME: Deprecated for 1995
206 generation_flag = GN_VER1995;
208 } else if (strcmp(gen,"2") == 0) { // FIXME: Deprecated for 2001
209 generation_flag = GN_VER2001;
211 } else if (strcmp(gen,"2x") == 0) { // FIXME: Deprecated for 2001
212 generation_flag = GN_VER2001;
213 gn_icarus_misc_flag = true;
215 } else if (strcmp(gen,"1995") == 0) {
216 generation_flag = GN_VER1995;
218 } else if (strcmp(gen,"2001") == 0) {
219 generation_flag = GN_VER2001;
221 } else if (strcmp(gen,"2005") == 0) {
222 generation_flag = GN_VER2005;
224 } else if (strcmp(gen,"icarus-misc") == 0) {
225 gn_icarus_misc_flag = true;
227 } else if (strcmp(gen,"no-icarus-misc") == 0) {
228 gn_icarus_misc_flag = false;
230 } else if (strcmp(gen,"xtypes") == 0) {
231 gn_cadence_types_flag = true;
233 } else if (strcmp(gen,"no-xtypes") == 0) {
234 gn_cadence_types_flag = false;
236 } else if (strcmp(gen,"specify") == 0) {
237 gn_specify_blocks_flag = true;
239 } else if (strcmp(gen,"no-specify") == 0) {
240 gn_specify_blocks_flag = false;
242 } else if (strcmp(gen,"verilog-ams") == 0) {
243 gn_verilog_ams_flag = true;
245 } else if (strcmp(gen,"no-verilog-ams") == 0) {
246 gn_verilog_ams_flag = false;
248 } else if (strcmp(gen,"io-range-error") == 0) {
249 gn_io_range_error_flag = true;
251 } else if (strcmp(gen,"no-io-range-error") == 0) {
252 gn_io_range_error_flag = false;
254 } else {
258 static void parm_to_flagmap(const string&flag)
260 string key;
261 const char*value;
262 unsigned off = flag.find('=');
263 if (off > flag.size()) {
264 key = flag;
265 value = "";
267 } else {
268 key = flag.substr(0, off);
269 value = strdup(flag.substr(off+1).c_str());
272 flags[key] = value;
276 * Read the contents of a config file. This file is a temporary
277 * configuration file made by the compiler driver to carry the bulky
278 * flags generated from the user. This reduces the size of the command
279 * line needed to invoke ivl.
281 * Each line of the iconfig file has the format:
283 * <keyword>:<value>
285 * The <value> is all the text after the ':' and up to but not
286 * including the end of the line. Thus, white spaces and ':'
287 * characters may appear here.
289 * The valid keys are:
291 * -y:<dir>
292 * -yl:<dir>
293 * -Y:<string>
295 * -T:<min/typ/max>
296 * Select which expression to use.
298 * -t:<target>
299 * Usually, "-t:dll"
301 * basedir:<path>
302 * Location to look for installed sub-components
304 * debug:<name>
305 * Activate a class of debug messages.
307 * depfile:<path>
308 * Give the path to an output dependency file.
310 * flag:<name>=<string>
311 * Generic compiler flag strings.
313 * functor:<name>
314 * Append a named functor to the processing path.
316 * generation:<1|2|2x|xtypes|no-xtypes|specify|no-specify>
317 * This is the generation flag
319 * ivlpp:<preprocessor command>
320 * This specifies the ivlpp command line used to process
321 * library modules as I read them in.
323 * iwidth:<bits>
324 * This specifies the width of integer variables. (that is,
325 * variables declared using the "integer" keyword.)
327 * library_file:<path>
328 * This marks that a source file with the given path is a
329 * library. Any modules in that file are marked as library
330 * modules.
332 * module:<name>
333 * Load a VPI module.
335 * out:<path>
336 * Path to the output file.
338 * sys_func:<path>
339 * Path to a system functions descriptor table
341 * root:<name>
342 * Specify a root module. There may be multiple of this.
344 * warnings:<string>
345 * Warning flag letters.
347 static void read_iconfig_file(const char*ipath)
349 char buf[8*1024];
351 FILE*ifile = fopen(ipath, "r");
352 if (ifile == 0) {
353 cerr << "ERROR: Unable to read config file: " << ipath << endl;
354 return;
357 while (fgets(buf, sizeof buf, ifile) != 0) {
358 if (buf[0] == '#')
359 continue;
360 char*cp = strchr(buf, ':');
361 if (cp == 0)
362 continue;
364 *cp++ = 0;
365 char*ep = cp + strlen(cp);
366 while (ep > cp) {
367 ep -= 1;
368 switch (*ep) {
369 case '\r':
370 case '\n':
371 case ' ':
372 case '\t':
373 *ep = 0;
374 break;
375 default:
376 ep = cp;
380 if (strcmp(buf, "basedir") == 0) {
381 basedir = strdup(cp);
383 } else if (strcmp(buf, "debug") == 0) {
384 if (strcmp(cp, "scopes") == 0) {
385 debug_scopes = true;
386 cerr << "debug: Enable scopes debug" << endl;
387 } else if (strcmp(cp,"eval_tree") == 0) {
388 debug_eval_tree = true;
389 cerr << "debug: Enable eval_tree debug" << endl;
390 } else if (strcmp(cp,"elaborate") == 0) {
391 debug_elaborate = true;
392 cerr << "debug: Enable elaborate debug" << endl;
393 } else if (strcmp(cp,"synth2") == 0) {
394 debug_synth2 = true;
395 cerr << "debug: Enable synth2 debug" << endl;
396 } else if (strcmp(cp,"optimizer") == 0) {
397 debug_optimizer = true;
398 cerr << "debug: Enable optimizer debug" << endl;
399 } else {
402 } else if (strcmp(buf, "depfile") == 0) {
403 depfile_name = strdup(cp);
405 } else if (strcmp(buf, "flag") == 0) {
406 string parm = cp;
407 parm_to_flagmap(parm);
409 } else if (strcmp(buf,"functor") == 0) {
410 if (strncmp(cp, "synth", 5) == 0) {
411 synthesis = true; // We are doing synthesis.
413 net_func tmp = name_to_net_func(cp);
414 if (tmp == 0) {
415 cerr << "No such design transform function ``"
416 << cp << "''." << endl;
417 flag_errors += 1;
418 break;
420 net_func_queue.push(tmp);
422 } else if (strcmp(buf, "generation") == 0) {
423 process_generation_flag(cp);
425 } else if (strcmp(buf, "ivlpp") == 0) {
426 ivlpp_string = strdup(cp);
428 } else if (strcmp(buf, "iwidth") == 0) {
429 integer_width = strtoul(cp,0,10);
431 } else if (strcmp(buf, "library_file") == 0) {
432 perm_string path = filename_strings.make(cp);
433 library_file_map[path] = true;
435 } else if (strcmp(buf,"module") == 0) {
436 if (vpi_module_list == 0) {
437 vpi_module_list = strdup(cp);
439 } else {
440 char*tmp = (char*)realloc(vpi_module_list,
441 strlen(vpi_module_list)
442 + strlen(cp)
443 + 2);
444 strcat(tmp, ",");
445 strcat(tmp, cp);
446 vpi_module_list = tmp;
448 flags["VPI_MODULE_LIST"] = vpi_module_list;
450 } else if (strcmp(buf, "out") == 0) {
451 flags["-o"] = strdup(cp);
453 } else if (strcmp(buf, "sys_func") == 0) {
454 load_sys_func_table(cp);
456 } else if (strcmp(buf, "root") == 0) {
457 roots.push_back(lex_strings.make(cp));
459 } else if (strcmp(buf,"warnings") == 0) {
460 /* Scan the warnings enable string for warning flags. */
461 for ( ; *cp ; cp += 1) switch (*cp) {
462 case 'i':
463 warn_implicit = true;
464 break;
465 case 'l':
466 warn_inf_loop = true;
467 break;
468 case 'p':
469 warn_portbinding = true;
470 break;
471 case 't':
472 warn_timescale = true;
473 break;
474 default:
475 break;
478 } else if (strcmp(buf, "-y") == 0) {
479 build_library_index(cp, CASE_SENSITIVE);
481 } else if (strcmp(buf, "-yl") == 0) {
482 build_library_index(cp, false);
484 } else if (strcmp(buf, "-Y") == 0) {
485 library_suff.push_back(strdup(cp));
487 } else if (strcmp(buf,"-t") == 0) {
488 target = strdup(cp);
490 } else if (strcmp(buf,"-T") == 0) {
491 if (strcmp(cp,"min") == 0) {
492 min_typ_max_flag = MIN;
493 min_typ_max_warn = 0;
494 } else if (strcmp(cp,"typ") == 0) {
495 min_typ_max_flag = TYP;
496 min_typ_max_warn = 0;
497 } else if (strcmp(cp,"max") == 0) {
498 min_typ_max_flag = MAX;
499 min_typ_max_warn = 0;
500 } else {
501 cerr << "Invalid argument (" << optarg << ") to -T flag."
502 << endl;
503 flag_errors += 1;
510 extern Design* elaborate(list <perm_string> root);
512 #if defined(HAVE_TIMES)
513 static double cycles_diff(struct tms *a, struct tms *b)
515 clock_t aa = a->tms_utime
516 + a->tms_stime
517 + a->tms_cutime
518 + a->tms_cstime;
520 clock_t bb = b->tms_utime
521 + b->tms_stime
522 + b->tms_cutime
523 + b->tms_cstime;
525 return (aa-bb)/(double)sysconf(_SC_CLK_TCK);
527 #else // ! defined(HAVE_TIMES)
528 // Provide dummies
529 struct tms { int x; };
530 inline static void times(struct tms *) { }
531 inline static double cycles_diff(struct tms *a, struct tms *b) { return 0; }
532 #endif // ! defined(HAVE_TIMES)
534 int main(int argc, char*argv[])
536 bool help_flag = false;
537 bool times_flag = false;
539 const char* net_path = 0;
540 const char* pf_path = 0;
541 int opt;
543 struct tms cycles[5];
545 library_suff.push_back(".v");
547 vpi_module_list = strdup("system");
548 flags["VPI_MODULE_LIST"] = vpi_module_list;
549 flags["-o"] = "a.out";
550 min_typ_max_flag = TYP;
551 min_typ_max_warn = 10;
553 while ((opt = getopt(argc, argv, "C:f:hN:P:p:Vv")) != EOF) switch (opt) {
555 case 'C':
556 read_iconfig_file(optarg);
557 break;
559 case 'f':
560 parm_to_flagmap(optarg);
561 break;
562 case 'h':
563 help_flag = true;
564 break;
565 case 'N':
566 net_path = optarg;
567 break;
568 case 'P':
569 pf_path = optarg;
570 break;
571 case 'p':
572 parm_to_flagmap(optarg);
573 break;
574 case 'v':
575 verbose_flag = true;
576 # if defined(HAVE_TIMES)
577 times_flag = true;
578 # endif
579 break;
580 case 'V':
581 cout << "Icarus Verilog version " << VERSION << endl;
582 cout << COPYRIGHT << endl;
583 cout << endl << NOTICE << endl;
584 return 0;
585 default:
586 flag_errors += 1;
587 break;
590 if (flag_errors)
591 return flag_errors;
593 if (help_flag) {
594 cout << "Icarus Verilog version " << VERSION << endl <<
595 "usage: ivl <options> <file>\n"
596 "options:\n"
597 "\t-C <name> Config file from driver.\n"
598 "\t-h Print usage information, and exit.\n"
599 "\t-N <file> Dump the elaborated netlist to <file>.\n"
600 "\t-P <file> Write the parsed input to <file>.\n"
601 "\t-p <assign> Set a parameter value.\n"
602 "\t-v Print progress indications"
603 #if defined(HAVE_TIMES)
604 " and execution times"
605 #endif
606 ".\n"
607 "\t-V Print version and copyright information, and exit.\n"
610 return 0;
613 if (optind == argc) {
614 cerr << "No input files." << endl;
615 return 1;
618 if( depfile_name ) {
619 depend_file = fopen(depfile_name, "a");
620 if(! depend_file) {
621 perror(depfile_name);
625 lexor_keyword_mask = 0;
626 switch (generation_flag) {
627 case GN_VER1995:
628 lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
629 break;
630 case GN_VER2001:
631 lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
632 lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
633 lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
634 break;
635 case GN_VER2005:
636 lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
637 lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
638 lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
639 lexor_keyword_mask |= GN_KEYWORDS_1364_2005;
640 break;
643 if (gn_cadence_types_flag)
644 lexor_keyword_mask |= GN_KEYWORDS_ICARUS;
646 if (gn_verilog_ams_flag)
647 lexor_keyword_mask |= GN_KEYWORDS_VAMS_2_3;
649 if (verbose_flag) {
650 if (times_flag)
651 times(cycles+0);
653 cout << "Using language generation: ";
654 switch (generation_flag) {
655 case GN_VER1995:
656 cout << "IEEE1364-1995";
657 break;
658 case GN_VER2001:
659 cout << "IEEE1364-2001";
660 break;
661 case GN_VER2005:
662 cout << "IEEE1364-2005";
663 break;
666 if (gn_verilog_ams_flag)
667 cout << ",verilog-ams";
669 if (gn_specify_blocks_flag)
670 cout << ",specify";
671 else
672 cout << ",no-specify";
674 if (gn_cadence_types_flag)
675 cout << ",xtypes";
676 else
677 cout << ",no-xtypes";
679 if (gn_icarus_misc_flag)
680 cout << ",icarus-misc";
681 else
682 cout << ",no-icarus-misc";
684 cout << endl << "PARSING INPUT" << endl;
687 /* Parse the input. Make the pform. */
688 int rc = pform_parse(argv[optind]);
690 if (pf_path) {
691 ofstream out (pf_path);
692 out << "PFORM DUMP NATURES:" << endl;
693 for (map<perm_string,nature_t*>::iterator cur = natures.begin()
694 ; cur != natures.end() ; cur ++ ) {
695 pform_dump(out, (*cur).second);
697 out << "PFORM DUMP DISCIPLINES:" << endl;
698 for (map<perm_string,discipline_t*>::iterator cur = disciplines.begin()
699 ; cur != disciplines.end() ; cur ++ ) {
700 pform_dump(out, (*cur).second);
702 out << "PFORM DUMP MODULES:" << endl;
703 for (map<perm_string,Module*>::iterator mod = pform_modules.begin()
704 ; mod != pform_modules.end()
705 ; mod ++ ) {
706 pform_dump(out, (*mod).second);
708 out << "PFORM DUMP PRIMITIVES:" << endl;
709 for (map<perm_string,PUdp*>::iterator idx = pform_primitives.begin()
710 ; idx != pform_primitives.end()
711 ; idx ++ ) {
712 (*idx).second->dump(out);
716 if (rc) {
717 return rc;
721 /* If the user did not give specific module(s) to start with,
722 then look for modules that are not instantiated anywhere. */
724 if (roots.empty()) {
725 map<perm_string,bool> mentioned_p;
726 map<perm_string,Module*>::iterator mod;
727 if (verbose_flag)
728 cout << "LOCATING TOP-LEVEL MODULES" << endl << " ";
729 for (mod = pform_modules.begin()
730 ; mod != pform_modules.end()
731 ; mod++) {
732 list<PGate*> gates = (*mod).second->get_gates();
733 list<PGate*>::const_iterator gate;
734 for (gate = gates.begin(); gate != gates.end(); gate++) {
735 PGModule *mod = dynamic_cast<PGModule*>(*gate);
736 if (mod) {
737 // Note that this module has been instantiated
738 mentioned_p[mod->get_type()] = true;
743 for (mod = pform_modules.begin()
744 ; mod != pform_modules.end()
745 ; mod++) {
747 /* Don't choose library modules. */
748 if ((*mod).second->library_flag)
749 continue;
751 /* Don't choose modules instantiated in other
752 modules. */
753 if (mentioned_p[(*mod).second->mod_name()])
754 continue;
756 /* What's left might as well be chosen as a root. */
757 if (verbose_flag)
758 cout << " " << (*mod).second->mod_name();
759 roots.push_back((*mod).second->mod_name());
761 if (verbose_flag)
762 cout << endl;
765 /* If there is *still* no guess for the root module, then give
766 up completely, and complain. */
768 if (roots.empty()) {
769 cerr << "No top level modules, and no -s option." << endl;
770 return 1;
774 if (verbose_flag) {
775 if (times_flag) {
776 times(cycles+1);
777 cerr<<" ... done, "
778 <<cycles_diff(cycles+1, cycles+0)<<" seconds."<<endl;
780 cout << "ELABORATING DESIGN" << endl;
783 /* On with the process of elaborating the module. */
784 Design*des = elaborate(roots);
786 if ((des == 0) || (des->errors > 0)) {
787 if (des != 0) {
788 cerr << des->errors
789 << " error(s) during elaboration." << endl;
790 if (net_path) {
791 ofstream out (net_path);
792 des->dump(out);
794 } else {
795 cerr << "Elaboration failed" << endl;
798 goto errors_summary;
801 des->set_flags(flags);
803 /* Done with all the pform data. Delete the modules. */
804 for (map<perm_string,Module*>::iterator idx = pform_modules.begin()
805 ; idx != pform_modules.end() ; idx ++) {
807 delete (*idx).second;
808 (*idx).second = 0;
811 if (verbose_flag) {
812 if (times_flag) {
813 times(cycles+2);
814 cerr<<" ... done, "
815 <<cycles_diff(cycles+2, cycles+1)<<" seconds."<<endl;
817 cout << "RUNNING FUNCTORS" << endl;
820 while (!net_func_queue.empty()) {
821 net_func func = net_func_queue.front();
822 net_func_queue.pop();
823 if (verbose_flag)
824 cerr<<" -F "<<net_func_to_name(func)<< " ..." <<endl;
825 func(des);
828 if (net_path) {
829 if (verbose_flag)
830 cerr<<" dumping netlist to " <<net_path<< "..." <<endl;
832 ofstream out (net_path);
833 des->dump(out);
836 if (des->errors) {
837 cerr << des->errors
838 << " error(s) in post-elaboration processing." <<
839 endl;
840 return des->errors;
843 if (verbose_flag) {
844 if (times_flag) {
845 times(cycles+3);
846 cerr<<" ... done, "
847 <<cycles_diff(cycles+3, cycles+2)<<" seconds."<<endl;
851 if (verbose_flag) {
852 cout << "CODE GENERATION -t "<<target<< endl;
855 int emit_rc;
856 emit_rc = emit(des, target);
857 if (emit_rc > 0) {
858 cerr << "error: Code generation had "
859 << emit_rc << " errors."
860 << endl;
861 return 1;
863 if (emit_rc < 0) {
864 cerr << "error: Code generator failure: " << emit_rc << endl;
865 return -1;
868 if (verbose_flag) {
869 if (times_flag) {
870 times(cycles+4);
871 cerr<<" ... done, "
872 <<cycles_diff(cycles+4, cycles+3)<<" seconds."<<endl;
873 } else {
874 cout << "DONE." << endl;
878 if (verbose_flag) {
879 cout << "STATISTICS" << endl;
880 cout << "lex_string:"
881 << " add_count=" << lex_strings.add_count()
882 << " hit_count=" << lex_strings.add_hit_count()
883 << endl;
886 return 0;
888 errors_summary:
889 if (missing_modules.size() > 0) {
890 cerr << "*** These modules were missing:" << endl;
892 map<perm_string,unsigned>::const_iterator idx;
893 for (idx = missing_modules.begin()
894 ; idx != missing_modules.end()
895 ; idx ++)
896 cerr << " " << (*idx).first
897 << " referenced " << (*idx).second
898 << " times."<< endl;
900 cerr << "***" << endl;
903 return des? des->errors : 1;