#include "lang_features.h"
#include "driver/firm_opt.h"
#include "driver/firm_cmdline.h"
+#include "driver/firm_timing.h"
#include "adt/error.h"
#include "wrappergen/write_fluffy.h"
#include "wrappergen/write_caml.h"
#ifndef PREPROCESSOR
#ifndef __WIN32__
-#define PREPROCESSOR "gcc -E -std=c99 -m32 -U__STRICT_ANSI__"
+#define PREPROCESSOR "gcc -E -m32 -U__STRICT_ANSI__"
#else
-#define PREPROCESSOR "cpp -std=c99 -m32 -U__STRICT_ANSI__"
+#define PREPROCESSOR "cpp -m32 -U__STRICT_ANSI__"
#endif
#endif
static char dep_target[1024];
static const char *outname;
+typedef enum lang_standard_t {
+ STANDARD_DEFAULT, /* gnu99 (for C, GCC does gnu89) or gnu++98 (for C++) */
+ STANDARD_ANSI, /* c89 (for C) or c++98 (for C++) */
+ STANDARD_C89, /* ISO C90 (sic) */
+ STANDARD_C90, /* ISO C90 as modified in amendment 1 */
+ STANDARD_C99, /* ISO C99 */
+ STANDARD_GNU89, /* ISO C90 plus GNU extensions (including some C99) */
+ STANDARD_GNU99, /* ISO C99 plus GNU extensions */
+ STANDARD_CXX98, /* ISO C++ 1998 plus amendments */
+ STANDARD_GNUXX98 /* ISO C++ 1998 plus amendments and GNU extensions */
+} lang_standard_t;
+
+static lang_standard_t standard;
+
typedef struct file_list_entry_t file_list_entry_t;
typedef enum filetype_t {
return get_atomic_kind_name(type->atomic.akind);
}
-static FILE *preprocess(const char *fname)
+static FILE *preprocess(const char *fname, filetype_t filetype)
{
- obstack_1grow(&cppflags_obst, '\0');
- const char *flags = obstack_finish(&cppflags_obst);
-
- obstack_printf(&cppflags_obst, "%s", PREPROCESSOR);
-
- /* setup default defines */
- add_flag(&cppflags_obst, "-U__WCHAR_TYPE__");
- add_flag(&cppflags_obst, "-D__WCHAR_TYPE__=%s", type_to_string(type_wchar_t));
- add_flag(&cppflags_obst, "-U__SIZE_TYPE__");
- add_flag(&cppflags_obst, "-D__SIZE_TYPE__=%s", type_to_string(type_size_t));
-
- /* TODO hack... */
- add_flag(&cppflags_obst, "-D__builtin_abort=abort");
- add_flag(&cppflags_obst, "-D__builtin_abs=abs");
- add_flag(&cppflags_obst, "-D__builtin_exit=exit");
- add_flag(&cppflags_obst, "-D__builtin_malloc=malloc");
- add_flag(&cppflags_obst, "-D__builtin_memcmp=memcmp");
- add_flag(&cppflags_obst, "-D__builtin_memcpy=memcpy");
- add_flag(&cppflags_obst, "-D__builtin_memset=memset");
- add_flag(&cppflags_obst, "-D__builtin_strlen=strlen");
- add_flag(&cppflags_obst, "-D__builtin_strcmp=strcmp");
- add_flag(&cppflags_obst, "-D__builtin_strcpy=strcpy");
+ static const char *common_flags = NULL;
+
+ if (common_flags == NULL) {
+ obstack_1grow(&cppflags_obst, '\0');
+ const char *flags = obstack_finish(&cppflags_obst);
+
+ /* setup default defines */
+ add_flag(&cppflags_obst, "-U__WCHAR_TYPE__");
+ add_flag(&cppflags_obst, "-D__WCHAR_TYPE__=%s", type_to_string(type_wchar_t));
+ add_flag(&cppflags_obst, "-U__SIZE_TYPE__");
+ add_flag(&cppflags_obst, "-D__SIZE_TYPE__=%s", type_to_string(type_size_t));
+
+ add_flag(&cppflags_obst, "-U__VERSION__");
+ add_flag(&cppflags_obst, "-D__VERSION__=\"%s\"", cparser_REVISION);
+
+ /* TODO hack... */
+ add_flag(&cppflags_obst, "-D__builtin_abort=abort");
+ add_flag(&cppflags_obst, "-D__builtin_abs=abs");
+ add_flag(&cppflags_obst, "-D__builtin_exit=exit");
+ add_flag(&cppflags_obst, "-D__builtin_malloc=malloc");
+ add_flag(&cppflags_obst, "-D__builtin_memcmp=memcmp");
+ add_flag(&cppflags_obst, "-D__builtin_memcpy=memcpy");
+ add_flag(&cppflags_obst, "-D__builtin_memset=memset");
+ add_flag(&cppflags_obst, "-D__builtin_strlen=strlen");
+ add_flag(&cppflags_obst, "-D__builtin_strcmp=strcmp");
+ add_flag(&cppflags_obst, "-D__builtin_strcpy=strcpy");
+
+ if (flags[0] != '\0') {
+ size_t len = strlen(flags);
+ obstack_1grow(&cppflags_obst, ' ');
+ obstack_grow(&cppflags_obst, flags, len);
+ }
+ obstack_1grow(&cppflags_obst, '\0');
+ common_flags = obstack_finish(&cppflags_obst);
+ }
+
+ assert(obstack_object_size(&cppflags_obst) == 0);
+
+ const char *preprocessor = getenv("CPARSER_PP");
+ if (preprocessor == NULL)
+ preprocessor = PREPROCESSOR;
+
+ obstack_printf(&cppflags_obst, "%s ", preprocessor);
+ switch (filetype) {
+ case FILETYPE_C:
+ add_flag(&cppflags_obst, "-std=c99");
+ break;
+ case FILETYPE_CXX:
+ add_flag(&cppflags_obst, "-std=c++98");
+ break;
+ case FILETYPE_ASSEMBLER:
+ add_flag(&cppflags_obst, "-x");
+ add_flag(&cppflags_obst, "assembler-with-cpp");
+ break;
+ default:
+ break;
+ }
+ obstack_printf(&cppflags_obst, "%s", common_flags);
/* handle dependency generation */
if (dep_target[0] != '\0') {
add_flag(&cppflags_obst, outname);
}
}
- if (flags[0] != '\0') {
- size_t len = strlen(flags);
- obstack_1grow(&cppflags_obst, ' ');
- obstack_grow(&cppflags_obst, flags, len);
- }
add_flag(&cppflags_obst, fname);
obstack_1grow(&cppflags_obst, '\0');
- const char *buf = obstack_finish(&cppflags_obst);
+ char *buf = obstack_finish(&cppflags_obst);
if (verbose) {
puts(buf);
}
exit(1);
}
+ /* we don't really need that anymore */
+ obstack_free(&cppflags_obst, buf);
+
return f;
}
{
char buf[65536];
- snprintf(buf, sizeof(buf), "%s %s -o %s", ASSEMBLER, in, out);
+ const char *assembler = getenv("CPARSER_AS");
+ if (assembler == NULL)
+ assembler = ASSEMBLER;
+
+ snprintf(buf, sizeof(buf), "%s %s -o %s", assembler, in, out);
if (verbose) {
puts(buf);
}
const char *flags = obstack_finish(&ldflags_obst);
/* construct commandline */
- obstack_printf(&ldflags_obst, "%s ", LINKER);
+ const char *linker = getenv("CPARSER_LINK");
+ if (linker == NULL)
+ linker = LINKER;
+ obstack_printf(&ldflags_obst, "%s ", linker);
obstack_printf(&ldflags_obst, "%s", flags);
obstack_1grow(&ldflags_obst, '\0');
}
}
-typedef enum lang_standard_t {
- STANDARD_DEFAULT, /* gnu99 (for C, GCC does gnu89) or gnu++98 (for C++) */
- STANDARD_ANSI, /* c89 (for C) or c++98 (for C++) */
- STANDARD_C89, /* ISO C90 (sic) */
- STANDARD_C90, /* ISO C90 as modified in amendment 1 */
- STANDARD_C99, /* ISO C99 */
- STANDARD_GNU89, /* ISO C90 plus GNU extensions (including some C99) */
- STANDARD_GNU99, /* ISO C99 plus GNU extensions */
- STANDARD_CXX98, /* ISO C++ 1998 plus amendments */
- STANDARD_GNUXX98 /* ISO C++ 1998 plus amendments and GNU extensions */
-} lang_standard_t;
-
int main(int argc, char **argv)
{
initialize_firm();
file_list_entry_t *files = NULL;
file_list_entry_t *last_file = NULL;
bool construct_dep_target = false;
+ bool do_timing = false;
struct obstack file_obst;
atexit(free_temp_files);
break;
default:
case 4:
- set_option("strict-aliasing");
/* use_builtins = true; */
/* fallthrough */
case 3:
- set_option("cond-eval");
+ set_option("thread-jumps");
set_option("if-conv");
/* fallthrough */
case 2:
+ set_option("strict-aliasing");
set_option("inline");
set_option("deconv");
set_be_option("omitfp");
}
/* parse rest of options */
- lang_standard_t standard = STANDARD_DEFAULT;
+ standard = STANDARD_DEFAULT;
unsigned features_on = 0;
unsigned features_off = 0;
filetype_t forced_filetype = FILETYPE_AUTODETECT;
GET_ARG_AFTER(opt, "-march=");
snprintf(arch_opt, sizeof(arch_opt), "%s-arch=%s", cpu_arch, opt);
int res = firm_be_option(arch_opt);
- if (res == 0)
+ if (res == 0) {
+ fprintf(stderr, "Unknown architecture '%s'\n", arch_opt);
argument_errors = true;
- else {
+ } else {
snprintf(arch_opt, sizeof(arch_opt), "%s-opt=%s", cpu_arch, opt);
int res = firm_be_option(arch_opt);
if (res == 0)
mode = PrintCaml;
} else if (streq(option, "print-jna")) {
mode = PrintJna;
+ } else if (streq(option, "time")) {
+ do_timing = true;
} else if (streq(option, "version")) {
print_cparser_version();
exit(EXIT_SUCCESS);
init_ast2firm();
init_mangle();
+ if (do_timing)
+ timer_init();
+
if (construct_dep_target) {
if (outname != 0 && strlen(outname) >= 2) {
get_output_name(dep_target, sizeof(dep_target), outname, ".d");
}
FILE *preprocessed_in = NULL;
+ filetype_t next_filetype = filetype;
switch (filetype) {
case FILETYPE_C:
- filetype = FILETYPE_PREPROCESSED_C;
+ next_filetype = FILETYPE_PREPROCESSED_C;
goto preprocess;
case FILETYPE_CXX:
- filetype = FILETYPE_PREPROCESSED_CXX;
+ next_filetype = FILETYPE_PREPROCESSED_CXX;
goto preprocess;
case FILETYPE_ASSEMBLER:
- filetype = FILETYPE_PREPROCESSED_ASSEMBLER;
- add_flag(&cppflags_obst, "-x");
- add_flag(&cppflags_obst, "assembler-with-cpp");
+ next_filetype = FILETYPE_PREPROCESSED_ASSEMBLER;
goto preprocess;
preprocess:
/* no support for input on FILE* yet */
if (in != NULL)
panic("internal compiler error: in for preprocessor != NULL");
- preprocessed_in = preprocess(filename);
+ preprocessed_in = preprocess(filename, filetype);
if (mode == PreprocessOnly) {
copy_file(out, preprocessed_in);
int result = pclose(preprocessed_in);
}
in = preprocessed_in;
+ filetype = next_filetype;
break;
default:
c_mode |= features_on;
c_mode &= ~features_off;
+ timer_push(TV_PARSING);
init_tokens();
translation_unit_t *const unit = do_parsing(in, filename);
+ timer_pop();
/* prints the AST even if errors occurred */
if (mode == PrintAst) {
continue;
}
+ timer_push(TV_CONSTRUCT);
translation_unit_to_firm(unit);
+ timer_pop();
graph_built:
if (mode == ParseOnly) {
const char *flags = obstack_finish(&ldflags_obst);
/* construct commandline */
- obstack_printf(&file_obst, "%s", LINKER);
+ const char *linker = getenv("CPARSER_LINK");
+ if (linker == NULL)
+ linker = LINKER;
+ obstack_printf(&file_obst, "%s", linker);
for (file_list_entry_t *entry = files; entry != NULL;
entry = entry->next) {
if (entry->type != FILETYPE_OBJECT)
}
}
+ if (do_timing)
+ timer_term(stderr);
+
obstack_free(&cppflags_obst, NULL);
obstack_free(&ldflags_obst, NULL);
obstack_free(&file_obst, NULL);