/*
* This file is part of cparser.
- * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
+ * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#define fdopen(fd, mode) _fdopen(fd, mode)
#define popen(cmd, mode) _popen(cmd, mode)
#define pclose(file) _pclose(file)
+#define unlink(filename) _unlink(filename)
#else
#include <unistd.h>
#define HAVE_MKSTEMP
#endif
-#ifndef WITH_LIBCORE
-#define WITH_LIBCORE
-#endif
-
#include <libfirm/firm.h>
#include <libfirm/be.h>
#include "lang_features.h"
#include "driver/firm_opt.h"
#include "driver/firm_cmdline.h"
+#include "driver/firm_timing.h"
#include "adt/error.h"
-#include "write_fluffy.h"
-#include "write_caml.h"
+#include "wrappergen/write_fluffy.h"
+#include "wrappergen/write_caml.h"
+#include "wrappergen/write_jna.h"
#include "revision.h"
#include "warning.h"
+#include "mangle.h"
+#include "printer.h"
#ifndef PREPROCESSOR
-#ifdef __APPLE__
-#define PREPROCESSOR "gcc -E -std=c99 -m32 -U__STRICT_ANSI__"
+#ifndef __WIN32__
+#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
#ifndef ASSEMBLER
#ifdef __APPLE__
-#define ASSEMBLER "gcc -c -xassembler"
+#define ASSEMBLER "gcc -m32 -c -xassembler"
#else
#define ASSEMBLER "as --32"
#endif
#endif
-/** The current c mode/dialect. */
-lang_features_t c_mode = _C89 | _ANSI | _C99 | _GNUC;
-
-/** The 'machine size', 16, 32 or 64 bit, 32bit is the default. */
-unsigned int machine_size = 32;
-
-/** true if the char type is signed. */
-bool char_is_signed = true;
-
-/** true for strict language checking. */
-bool strict_mode = false;
-
-/** use builtins for some libc functions */
-bool use_builtins = false;
-
-/** we have extern function with const attribute. */
-bool have_const_functions = false;
+unsigned int c_mode = _C89 | _ANSI | _C99 | _GNUC;
+unsigned int machine_size = 32;
+bool byte_order_big_endian = false;
+bool char_is_signed = true;
+bool strict_mode = false;
+bool use_builtins = false;
+bool have_const_functions = false;
+atomic_type_kind_t wchar_atomic_kind = ATOMIC_TYPE_INT;
/* to switch on printing of implicit casts */
extern bool print_implicit_casts;
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 {
FILETYPE_ASSEMBLER,
FILETYPE_PREPROCESSED_ASSEMBLER,
FILETYPE_OBJECT,
+ FILETYPE_IR,
FILETYPE_UNKNOWN
} filetype_t;
static file_list_entry_t *temp_files;
-#if defined(_DEBUG) || defined(FIRM_DEBUG)
-/**
- * Debug printf implementation.
- *
- * @param fmt printf style format parameter
- */
-void dbg_printf(const char *fmt, ...)
-{
- va_list list;
-
- if (firm_dump.debug_print) {
- va_start(list, fmt);
- vprintf(fmt, list);
- va_end(list);
- } /* if */
-}
-#endif /* defined(_DEBUG) || defined(FIRM_DEBUG) */
-
static void initialize_firm(void)
{
firm_early_init();
-
- dump_consts_local(1);
- dump_keepalive_edges(1);
}
static void get_output_name(char *buf, size_t buflen, const char *inputname,
const char *newext)
{
- size_t last_dot = 0xffffffff;
- size_t i = 0;
-
- if(inputname == NULL) {
- snprintf(buf, buflen, "a%s", newext);
- return;
- }
-
- for(const char *c = inputname; *c != 0; ++c) {
- if(*c == '.')
- last_dot = i;
- ++i;
- }
- if(last_dot == 0xffffffff)
- last_dot = i;
-
- if(last_dot >= buflen)
- panic("filename too long");
- memcpy(buf, inputname, last_dot);
-
- size_t extlen = strlen(newext) + 1;
- if(extlen + last_dot >= buflen)
+ if (inputname == NULL)
+ inputname = "a";
+
+ char const *const last_slash = strrchr(inputname, '/');
+ char const *const filename =
+ last_slash != NULL ? last_slash + 1 : inputname;
+ char const *const last_dot = strrchr(filename, '.');
+ char const *const name_end =
+ last_dot != NULL ? last_dot : strchr(filename, '\0');
+
+ int const len = snprintf(buf, buflen, "%.*s%s",
+ (int)(name_end - filename), filename, newext);
+#ifdef _WIN32
+ if (len < 0 || buflen <= (size_t)len)
+#else
+ if (buflen <= (size_t)len)
+#endif
panic("filename too long");
- memcpy(buf+last_dot, newext, extlen);
}
-#include "builtins.h"
+#include "gen_builtins.h"
static translation_unit_t *do_parsing(FILE *const in, const char *const input_name)
{
do {
lexer_next_preprocessing_token();
print_token(stdout, &lexer_token);
- puts("");
- } while(lexer_token.type != T_EOF);
+ putchar('\n');
+ } while (lexer_token.type != T_EOF);
}
static void add_flag(struct obstack *obst, const char *format, ...)
{
+ char buf[65536];
va_list ap;
- va_start(ap, format);
- char buf[4096];
- vsnprintf(buf, sizeof(buf), format, ap);
+ va_start(ap, format);
+#ifdef _WIN32
+ int len =
+#endif
+ vsnprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
- /* escape stuff... */
obstack_1grow(obst, ' ');
+#ifdef _WIN32
+ obstack_1grow(obst, '"');
+ obstack_grow(obst, buf, len);
+ obstack_1grow(obst, '"');
+#else
+ /* escape stuff... */
for (char *c = buf; *c != '\0'; ++c) {
switch(*c) {
- case '"':
- case '\'':
- case '`':
case ' ':
- case '\t':
- case '\n':
- case '\r':
- case '\\':
+ case '"':
case '$':
+ case '&':
case '(':
case ')':
+ case ';':
+ case '<':
+ case '>':
+ case '\'':
+ case '\\':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '`':
+ case '|':
obstack_1grow(obst, '\\');
- /* fallthrough */
+ /* FALLTHROUGH */
default:
obstack_1grow(obst, *c);
break;
}
}
-
- va_end(ap);
+#endif
}
static const char *type_to_string(type_t *type)
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);
+ 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);
+
+ 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);
+ }
- obstack_printf(&cppflags_obst, "%s", PREPROCESSOR);
+ assert(obstack_object_size(&cppflags_obst) == 0);
- /* 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));
+ 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, "-MF");
- add_flag(&cppflags_obst, "%s", dep_target);
+ add_flag(&cppflags_obst, dep_target);
if (outname != NULL) {
add_flag(&cppflags_obst, "-MQ");
- add_flag(&cppflags_obst, "%s", outname);
+ add_flag(&cppflags_obst, outname);
}
}
- if (flags[0] != '\0') {
- obstack_printf(&cppflags_obst, " %s", flags);
- }
- add_flag(&cppflags_obst, "%s", fname);
+ add_flag(&cppflags_obst, fname);
obstack_1grow(&cppflags_obst, '\0');
- const char *buf = obstack_finish(&cppflags_obst);
- if(verbose) {
+ char *buf = obstack_finish(&cppflags_obst);
+ if (verbose) {
puts(buf);
}
FILE *f = popen(buf, "r");
- if(f == NULL) {
+ if (f == NULL) {
fprintf(stderr, "invoking preprocessor failed\n");
exit(1);
}
+ /* we don't really need that anymore */
+ obstack_free(&cppflags_obst, buf);
+
return f;
}
static void assemble(const char *out, const char *in)
{
- char buf[4096];
+ char buf[65536];
+
+ const char *assembler = getenv("CPARSER_AS");
+ if (assembler == NULL)
+ assembler = ASSEMBLER;
- snprintf(buf, sizeof(buf), "%s %s -o %s", ASSEMBLER, in, out);
- if(verbose) {
+ snprintf(buf, sizeof(buf), "%s %s -o %s", assembler, in, out);
+ if (verbose) {
puts(buf);
}
int err = system(buf);
- if(err != 0) {
+ if (err != 0) {
fprintf(stderr, "assembler reported an error\n");
exit(1);
}
}
+static void print_file_name(const char *file)
+{
+ add_flag(&ldflags_obst, "-print-file-name=%s", file);
+
+ obstack_1grow(&ldflags_obst, '\0');
+ const char *flags = obstack_finish(&ldflags_obst);
+
+ /* construct commandline */
+ 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');
+
+ char *commandline = obstack_finish(&ldflags_obst);
+
+ if (verbose) {
+ puts(commandline);
+ }
+ int err = system(commandline);
+ if (err != EXIT_SUCCESS) {
+ fprintf(stderr, "linker reported an error\n");
+ exit(1);
+ }
+}
+
static const char *try_dir(const char *dir)
{
- if(dir == NULL)
+ if (dir == NULL)
return dir;
- if(access(dir, R_OK | W_OK | X_OK) == 0)
+ if (access(dir, R_OK | W_OK | X_OK) == 0)
return dir;
return NULL;
}
{
static const char *tmpdir = NULL;
- if(tmpdir != NULL)
+ if (tmpdir != NULL)
return tmpdir;
- if(tmpdir == NULL)
+ if (tmpdir == NULL)
tmpdir = try_dir(getenv("TMPDIR"));
- if(tmpdir == NULL)
+ if (tmpdir == NULL)
tmpdir = try_dir(getenv("TMP"));
- if(tmpdir == NULL)
+ if (tmpdir == NULL)
tmpdir = try_dir(getenv("TEMP"));
#ifdef P_tmpdir
- if(tmpdir == NULL)
+ if (tmpdir == NULL)
tmpdir = try_dir(P_tmpdir);
#endif
- if(tmpdir == NULL)
+ if (tmpdir == NULL)
tmpdir = try_dir("/var/tmp");
- if(tmpdir == NULL)
+ if (tmpdir == NULL)
tmpdir = try_dir("/usr/tmp");
- if(tmpdir == NULL)
+ if (tmpdir == NULL)
tmpdir = try_dir("/tmp");
- if(tmpdir == NULL)
+ if (tmpdir == NULL)
tmpdir = ".";
return tmpdir;
snprintf(buffer, buflen, "%s/%sXXXXXX", tempdir, prefix);
int fd = mkstemp(buffer);
- if(fd == -1) {
+ if (fd == -1) {
fprintf(stderr, "couldn't create temporary file: %s\n",
strerror(errno));
exit(1);
}
FILE *out = fdopen(fd, "w");
- if(out == NULL) {
+ if (out == NULL) {
fprintf(stderr, "couldn't create temporary file FILE*\n");
exit(1);
}
ParseOnly,
Compile,
CompileDump,
+ CompileExportIR,
CompileAssemble,
CompileAssembleLink,
LexTest,
PrintAst,
PrintFluffy,
- PrintCaml
+ PrintCaml,
+ PrintJna
} compile_mode_t;
static void usage(const char *argv0)
{
- fprintf(stderr, "Usage %s input [-o output] [-c]\n", argv0);
+ fprintf(stderr, "Usage %s [options] input [-o output]\n", argv0);
}
-static void print_cparser_version(void) {
- firm_version_t ver;
- firm_get_version(&ver);
-
+static void print_cparser_version(void)
+{
printf("cparser (%s) using libFirm (%u.%u",
- cparser_REVISION, ver.major, ver.minor);
- if(ver.revision[0] != 0) {
+ cparser_REVISION, ir_get_version_major(),
+ ir_get_version_minor());
+
+ const char *revision = ir_get_version_revision();
+ if (revision[0] != 0) {
putchar(' ');
- fputs(ver.revision, stdout);
+ fputs(revision, stdout);
}
- if(ver.build[0] != 0) {
+
+ const char *build = ir_get_version_build();
+ if (build[0] != 0) {
putchar(' ');
- fputs(ver.build, stdout);
+ fputs(build, stdout);
}
- puts(")\n");
+ puts(")");
+ puts("This is free software; see the source for copying conditions. There is NO\n"
+ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
+}
+
+static void print_help(const char *argv0)
+{
+ usage(argv0);
+ puts("");
+ puts("\t-fhelp Display help about firm optimisation options");
+ puts("\t-bhelp Display help about firm backend options");
+ puts("A big number of gcc flags is also supported");
}
static void set_be_option(const char *arg)
{
- int res = firm_be_option(arg);
+ int res = be_parse_arg(arg);
(void) res;
assert(res);
}
while (!feof(input) && !ferror(dest)) {
size_t read = fread(buf, 1, sizeof(buf), input);
- if(fwrite(buf, 1, read, dest) != read) {
+ if (fwrite(buf, 1, read, dest) != read) {
perror("couldn't write output");
}
}
}
FILE *in = fopen(filename, "r");
- if(in == NULL) {
+ if (in == NULL) {
fprintf(stderr, "Couldn't open '%s': %s\n", filename,
strerror(errno));
exit(1);
}
}
-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();
const char *dumpfunction = NULL;
+ const char *print_file_name_file = NULL;
compile_mode_t mode = CompileAssembleLink;
int opt_level = 1;
int result = EXIT_SUCCESS;
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);
#define GET_ARG_AFTER(def, args) \
def = &arg[sizeof(args)-1]; \
- if(def[0] == '\0') { \
+ if (def[0] == '\0') { \
++i; \
- if(i >= argc) { \
+ if (i >= argc) { \
fprintf(stderr, "error: expected argument after '" args "'\n"); \
argument_errors = true; \
break; \
} \
def = argv[i]; \
- if(def[0] == '-' && def[1] != '\0') { \
+ if (def[0] == '-' && def[1] != '\0') { \
fprintf(stderr, "error: expected argument after '" args "'\n"); \
argument_errors = true; \
continue; \
/* early options parsing (find out optimisation level and OS) */
for (int i = 1; i < argc; ++i) {
const char *arg = argv[i];
- if(arg[0] != '-')
+ if (arg[0] != '-')
continue;
const char *option = &arg[1];
break;
default:
case 4:
- set_option("strict-aliasing");
/* use_builtins = true; */
/* fallthrough */
case 3:
- set_option("cond-eval");
- set_option("if-conv");
+ set_option("thread-jumps");
+ set_option("if-conversion");
/* 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;
- lang_features_t features_on = 0;
- lang_features_t features_off = 0;
+ standard = STANDARD_DEFAULT;
+ unsigned features_on = 0;
+ unsigned features_off = 0;
filetype_t forced_filetype = FILETYPE_AUTODETECT;
bool help_displayed = false;
bool argument_errors = false;
- for(int i = 1; i < argc; ++i) {
+ for (int i = 1; i < argc; ++i) {
const char *arg = argv[i];
if (arg[0] == '-' && arg[1] != '\0') {
/* an option */
const char *option = &arg[1];
- if(option[0] == 'o') {
+ if (option[0] == 'o') {
GET_ARG_AFTER(outname, "-o");
- } else if(option[0] == 'g') {
+ } else if (option[0] == 'g') {
set_be_option("debuginfo=stabs");
set_be_option("omitfp=no");
set_be_option("ia32-nooptcc=yes");
- } else if(SINGLE_OPTION('c')) {
+ } else if (SINGLE_OPTION('c')) {
mode = CompileAssemble;
- } else if(SINGLE_OPTION('E')) {
+ } else if (SINGLE_OPTION('E')) {
mode = PreprocessOnly;
- } else if(SINGLE_OPTION('S')) {
+ } else if (SINGLE_OPTION('S')) {
mode = Compile;
- } else if(option[0] == 'O') {
+ } else if (option[0] == 'O') {
continue;
- } else if(option[0] == 'I') {
+ } else if (option[0] == 'I') {
const char *opt;
GET_ARG_AFTER(opt, "-I");
add_flag(&cppflags_obst, "-I%s", opt);
- } else if(option[0] == 'D') {
+ } else if (option[0] == 'D') {
const char *opt;
GET_ARG_AFTER(opt, "-D");
add_flag(&cppflags_obst, "-D%s", opt);
- } else if(option[0] == 'U') {
+ } else if (option[0] == 'U') {
const char *opt;
GET_ARG_AFTER(opt, "-U");
add_flag(&cppflags_obst, "-U%s", opt);
- } else if(option[0] == 'l') {
+ } else if (option[0] == 'l') {
const char *opt;
GET_ARG_AFTER(opt, "-l");
add_flag(&ldflags_obst, "-l%s", opt);
- } else if(option[0] == 'L') {
+ } else if (option[0] == 'L') {
const char *opt;
GET_ARG_AFTER(opt, "-L");
add_flag(&ldflags_obst, "-L%s", opt);
- } else if(SINGLE_OPTION('v')) {
+ } else if (SINGLE_OPTION('v')) {
verbose = 1;
- } else if(SINGLE_OPTION('w')) {
+ } else if (SINGLE_OPTION('w')) {
memset(&warning, 0, sizeof(warning));
- } else if(option[0] == 'x') {
+ } else if (option[0] == 'x') {
const char *opt;
GET_ARG_AFTER(opt, "-x");
forced_filetype = get_filetype_from_string(opt);
streq(option, "MD")) {
construct_dep_target = true;
add_flag(&cppflags_obst, "-%s", option);
- } else if(streq(option, "MM") ||
+ } else if (streq(option, "MM") ||
streq(option, "MP")) {
add_flag(&cppflags_obst, "-%s", option);
} else if (streq(option, "MT") ||
GET_ARG_AFTER(opt, "-MT");
add_flag(&cppflags_obst, "-%s", option);
add_flag(&cppflags_obst, "%s", opt);
+ } else if (streq(option, "include")) {
+ const char *opt;
+ GET_ARG_AFTER(opt, "-include");
+ add_flag(&cppflags_obst, "-include");
+ add_flag(&cppflags_obst, "%s", opt);
+ } else if (streq(option, "isystem")) {
+ const char *opt;
+ GET_ARG_AFTER(opt, "-isystem");
+ add_flag(&cppflags_obst, "-isystem");
+ add_flag(&cppflags_obst, "%s", opt);
+ } else if (streq(option, "nostdinc")
+ || streq(option, "trigraphs")) {
+ /* pass these through to the preprocessor */
+ add_flag(&cppflags_obst, "%s", arg);
} else if (streq(option, "pipe")) {
/* here for gcc compatibility */
} else if (option[0] == 'f') {
char const *orig_opt;
GET_ARG_AFTER(orig_opt, "-f");
- if (strstart(orig_opt, "align-loops=") ||
- strstart(orig_opt, "align-jumps=") ||
- strstart(orig_opt, "align-functions=")) {
- fprintf(stderr, "ignoring gcc option '-f%s'\n", orig_opt);
+ if (strstart(orig_opt, "input-charset=")) {
+ char const* const encoding = strchr(orig_opt, '=') + 1;
+ select_input_encoding(encoding);
+ } else if (streq(orig_opt, "verbose-asm")) {
+ /* ignore: we always print verbose assembler */
} else {
char const *opt = orig_opt;
bool truth_value = true;
opt += 3;
}
- if (streq(opt, "dollars-in-identifiers")) {
- allow_dollar_in_symbol = truth_value;
- } if (streq(opt, "builtins")) {
+ if (streq(opt, "builtins")) {
use_builtins = truth_value;
+ } else if (streq(opt, "dollars-in-identifiers")) {
+ allow_dollar_in_symbol = truth_value;
+ } else if (streq(opt, "omit-frame-pointer")) {
+ set_be_option(truth_value ? "omitfp" : "omitfp=no");
} else if (streq(opt, "short-wchar")) {
wchar_atomic_kind = truth_value ? ATOMIC_TYPE_USHORT
: ATOMIC_TYPE_INT;
- } else if (streq(opt, "syntax-only")) {
- mode = truth_value ? ParseOnly : CompileAssembleLink;
- } else if (streq(opt, "omit-frame-pointer")) {
- set_be_option(truth_value ? "omitfp" : "omitfp=no");
+ } else if (streq(opt, "signed-char")) {
+ char_is_signed = truth_value;
} else if (streq(opt, "strength-reduce")) {
firm_option(truth_value ? "strength-red" : "no-strength-red");
+ } else if (streq(opt, "syntax-only")) {
+ mode = truth_value ? ParseOnly : CompileAssembleLink;
+ } else if (streq(opt, "unsigned-char")) {
+ char_is_signed = !truth_value;
+ } else if (truth_value == false &&
+ streq(opt, "asynchronous-unwind-tables")) {
+ /* nothing todo, a gcc feature which we don't support
+ * anyway was deactivated */
+ } else if (strstart(orig_opt, "align-loops=") ||
+ strstart(orig_opt, "align-jumps=") ||
+ strstart(orig_opt, "align-functions=")) {
+ fprintf(stderr, "ignoring gcc option '-f%s'\n", orig_opt);
+ } else if (strstart(orig_opt, "message-length=")) {
+ /* ignore: would only affect error message format */
} else if (streq(opt, "fast-math") ||
streq(opt, "jump-tables") ||
- streq(opt, "unroll-loops") ||
streq(opt, "expensive-optimizations") ||
streq(opt, "common") ||
- streq(opt, "PIC") ||
+ streq(opt, "optimize-sibling-calls") ||
streq(opt, "align-loops") ||
streq(opt, "align-jumps") ||
- streq(opt, "align-functions")) {
+ streq(opt, "align-functions") ||
+ streq(opt, "PIC")) {
fprintf(stderr, "ignoring gcc option '-f%s'\n", orig_opt);
} else {
int res = firm_option(orig_opt);
} else if (option[0] == 'b') {
const char *opt;
GET_ARG_AFTER(opt, "-b");
- int res = firm_be_option(opt);
+ int res = be_parse_arg(opt);
if (res == 0) {
fprintf(stderr, "error: unknown Firm backend option '-b %s'\n",
opt);
strncpy(cpu_arch, opt, sizeof(cpu_arch));
}
} else if (option[0] == 'W') {
- if (strstart(option + 1, "l,")) // a gcc-style linker option
- {
+ if (option[1] == '\0') {
+ /* ignore -W, out defaults are already quiet verbose */
+ } else if (strstart(option + 1, "p,")) {
+ // pass options directly to the preprocessor
+ const char *opt;
+ GET_ARG_AFTER(opt, "-Wp,");
+ add_flag(&cppflags_obst, "-Wp,%s", opt);
+ } else if (strstart(option + 1, "l,")) {
+ // pass options directly to the linker
const char *opt;
GET_ARG_AFTER(opt, "-Wl,");
add_flag(&ldflags_obst, "-Wl,%s", opt);
+ } else if (streq(option + 1, "no-trigraphs")
+ || streq(option + 1, "undef")) {
+ add_flag(&cppflags_obst, "%s", arg);
+ } else {
+ set_warning_opt(&option[1]);
}
- else set_warning_opt(&option[1]);
- } else if(option[0] == 'm') {
+ } else if (option[0] == 'm') {
/* -m options */
const char *opt;
char arch_opt[64];
if (strstart(opt, "arch=")) {
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)
+ int res = be_parse_arg(arch_opt);
+ 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);
+ int res = be_parse_arg(arch_opt);
if (res == 0)
argument_errors = true;
}
} else if (strstart(opt, "tune=")) {
GET_ARG_AFTER(opt, "-mtune=");
snprintf(arch_opt, sizeof(arch_opt), "%s-opt=%s", cpu_arch, opt);
- int res = firm_be_option(arch_opt);
+ int res = be_parse_arg(arch_opt);
if (res == 0)
argument_errors = true;
} else if (strstart(opt, "cpu=")) {
GET_ARG_AFTER(opt, "-mcpu=");
snprintf(arch_opt, sizeof(arch_opt), "%s-arch=%s", cpu_arch, opt);
- int res = firm_be_option(arch_opt);
+ int res = be_parse_arg(arch_opt);
if (res == 0)
argument_errors = true;
} else if (strstart(opt, "fpmath=")) {
fprintf(stderr, "error: option -mfpumath supports only 387 or sse\n");
argument_errors = true;
}
- if(!argument_errors) {
+ if (!argument_errors) {
snprintf(arch_opt, sizeof(arch_opt), "%s-fpunit=%s", cpu_arch, opt);
- int res = firm_be_option(arch_opt);
+ int res = be_parse_arg(arch_opt);
if (res == 0)
argument_errors = true;
}
} else if (strstart(opt, "preferred-stack-boundary=")) {
GET_ARG_AFTER(opt, "-mpreferred-stack-boundary=");
snprintf(arch_opt, sizeof(arch_opt), "%s-stackalign=%s", cpu_arch, opt);
- int res = firm_be_option(arch_opt);
+ int res = be_parse_arg(arch_opt);
if (res == 0)
argument_errors = true;
} else if (streq(opt, "omit-leaf-frame-pointer")) {
set_be_option("omitleaffp=1");
} else if (streq(opt, "no-omit-leaf-frame-pointer")) {
set_be_option("omitleaffp=0");
+ } else if (streq(opt, "rtd")) {
+ default_calling_convention = CC_STDCALL;
+ } else if (strstart(opt, "regparm=")) {
+ fprintf(stderr, "error: regparm convention not supported yet\n");
+ argument_errors = true;
+ } else if (streq(opt, "soft-float")) {
+ fprintf(stderr, "error: software floatingpoint not supported yet\n");
+ argument_errors = true;
} else {
char *endptr;
long int value = strtol(opt, &endptr, 10);
(fprintf(stderr, "warning: ignoring gcc option '%s'\n", arg), standard);
} else if (streq(option, "version")) {
print_cparser_version();
+ } else if (strstart(option, "print-file-name=")) {
+ GET_ARG_AFTER(print_file_name_file, "-print-file-name=");
} else if (option[0] == '-') {
/* double dash option */
++option;
} else if (streq(option, "no-ms")) {
features_on &= ~_MS;
features_off |= _MS;
- } else if (streq(option, "signed-chars")) {
- char_is_signed = true;
- } else if (streq(option, "unsigned-chars")) {
- char_is_signed = false;
} else if (streq(option, "strict")) {
strict_mode = true;
} else if (streq(option, "lextest")) {
mode = PrintFluffy;
} else if (streq(option, "print-caml")) {
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);
+ } else if (streq(option, "help")) {
+ print_help(argv[0]);
+ help_displayed = true;
} else if (streq(option, "dump-function")) {
++i;
- if(i >= argc) {
+ if (i >= argc) {
fprintf(stderr, "error: "
"expected argument after '--dump-function'\n");
argument_errors = true;
}
dumpfunction = argv[i];
mode = CompileDump;
+ } else if (streq(option, "export-ir")) {
+ mode = CompileExportIR;
} else {
fprintf(stderr, "error: unknown argument '%s'\n", arg);
argument_errors = true;
streq(suffix, "cpp") ? FILETYPE_CXX :
streq(suffix, "cxx") ? FILETYPE_CXX :
streq(suffix, "h") ? FILETYPE_C :
+ streq(suffix, "ir") ? FILETYPE_IR :
streq(suffix, "o") ? FILETYPE_OBJECT :
streq(suffix, "s") ? FILETYPE_PREPROCESSED_ASSEMBLER :
streq(suffix, "so") ? FILETYPE_OBJECT :
- FILETYPE_AUTODETECT;
+ FILETYPE_OBJECT; /* gcc behavior: unknown file extension means object file */
}
}
-
- if (type == FILETYPE_AUTODETECT) {
- fprintf(stderr, "'%s': file format not recognized\n", arg);
- continue;
- }
}
file_list_entry_t *entry
}
}
+ if (help_displayed) {
+ return !argument_errors;
+ }
+
+ if (print_file_name_file != NULL) {
+ print_file_name(print_file_name_file);
+ return 0;
+ }
if (files == NULL) {
fprintf(stderr, "error: no input files specified\n");
argument_errors = true;
}
- if (help_displayed) {
- return !argument_errors;
- }
if (argument_errors) {
usage(argv[0]);
return 1;
/* we do the lowering in ast2firm */
firm_opt.lower_bitfields = FALSE;
+ /* set the c_mode here, types depends on it */
+ c_mode |= features_on;
+ c_mode &= ~features_off;
+
gen_firm_init();
+ byte_order_big_endian = be_get_backend_param()->byte_order_big_endian;
init_symbol_table();
init_types();
init_typehash();
init_ast();
init_parser();
init_ast2firm();
+ init_mangle();
+
+ if (do_timing)
+ timer_init();
if (construct_dep_target) {
if (outname != 0 && strlen(outname) >= 2) {
case PrintAst:
case PrintFluffy:
case PrintCaml:
+ case PrintJna:
case LexTest:
case PreprocessOnly:
case ParseOnly:
".vcg");
outname = outnamebuf;
break;
+ case CompileExportIR:
+ get_output_name(outnamebuf, sizeof(outnamebuf), filename, ".ir");
+ outname = outnamebuf;
+ break;
case CompileAssembleLink:
#ifdef _WIN32
outname = "a.exe";
out = stdout;
} else {
out = fopen(outname, "w");
- if(out == NULL) {
+ if (out == NULL) {
fprintf(stderr, "Couldn't open '%s' for writing: %s\n", outname,
strerror(errno));
return 1;
}
file_list_entry_t *file;
+ bool already_constructed_firm = false;
for (file = files; file != NULL; file = file->next) {
char asm_tempfile[1024];
const char *filename = file->name;
}
FILE *preprocessed_in = NULL;
+ filetype_t next_filetype = filetype;
switch (filetype) {
- case FILETYPE_C: filetype = FILETYPE_PREPROCESSED_C; goto preprocess;
- case FILETYPE_CXX: filetype = FILETYPE_PREPROCESSED_CXX; goto preprocess;
- case FILETYPE_ASSEMBLER: filetype = FILETYPE_PREPROCESSED_ASSEMBLER; goto preprocess;
+ case FILETYPE_C:
+ next_filetype = FILETYPE_PREPROCESSED_C;
+ goto preprocess;
+ case FILETYPE_CXX:
+ next_filetype = FILETYPE_PREPROCESSED_CXX;
+ goto preprocess;
+ case FILETYPE_ASSEMBLER:
+ 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);
fclose(out);
+ /* remove output file in case of error */
+ if (out != stdout && result != EXIT_SUCCESS) {
+ unlink(outname);
+ }
return result;
}
in = preprocessed_in;
+ filetype = next_filetype;
break;
default:
}
FILE *asm_out;
- if(mode == Compile) {
+ if (mode == Compile) {
asm_out = out;
} else {
asm_out = make_temp_file(asm_tempfile, sizeof(asm_tempfile), "ccs");
switch (standard) {
case STANDARD_ANSI:
case STANDARD_C89: c_mode = _C89; break;
- /* TODO ^v determine difference between these two */
+ /* TODO determine difference between these two */
case STANDARD_C90: c_mode = _C89; break;
case STANDARD_C99: c_mode = _C89 | _C99; break;
case STANDARD_GNU89: c_mode = _C89 | _GNUC; break;
do_parsing:
c_mode |= features_on;
c_mode &= ~features_off;
+
+ /* do the actual parsing */
+ ir_timer_t *t_parsing = ir_timer_new();
+ timer_register(t_parsing, "Frontend: Parsing");
+ timer_push(t_parsing);
init_tokens();
translation_unit_t *const unit = do_parsing(in, filename);
+ timer_pop(t_parsing);
/* prints the AST even if errors occurred */
if (mode == PrintAst) {
- type_set_output(out);
- ast_set_output(out);
+ print_to_file(out);
print_ast(unit);
}
- if(error_count > 0) {
+ if (error_count > 0) {
/* parsing failed because of errors */
fprintf(stderr, "%u error(s), %u warning(s)\n", error_count,
warning_count);
result = EXIT_FAILURE;
continue;
- } else if(warning_count > 0) {
+ } else if (warning_count > 0) {
fprintf(stderr, "%u warning(s)\n", warning_count);
}
if (in == preprocessed_in) {
int pp_result = pclose(preprocessed_in);
if (pp_result != EXIT_SUCCESS) {
+ /* remove output file */
+ if (out != stdout)
+ unlink(outname);
exit(EXIT_FAILURE);
}
}
- if(mode == BenchmarkParser) {
+ if (mode == BenchmarkParser) {
return result;
- } else if(mode == PrintFluffy) {
+ } else if (mode == PrintFluffy) {
write_fluffy_decls(out, unit);
continue;
} else if (mode == PrintCaml) {
write_caml_decls(out, unit);
continue;
+ } else if (mode == PrintJna) {
+ write_jna_decls(out, unit);
+ continue;
}
+ /* build the firm graph */
+ ir_timer_t *t_construct = ir_timer_new();
+ timer_register(t_construct, "Frontend: Graph construction");
+ timer_push(t_construct);
+ if (already_constructed_firm) {
+ panic("compiling multiple files/translation units not possible");
+ }
translation_unit_to_firm(unit);
+ already_constructed_firm = true;
+ timer_pop(t_construct);
+graph_built:
if (mode == ParseOnly) {
continue;
}
ident *id = new_id_from_str(dumpfunction);
ir_graph *irg = NULL;
int n_irgs = get_irp_n_irgs();
- for(int i = 0; i < n_irgs; ++i) {
+ for (int i = 0; i < n_irgs; ++i) {
ir_graph *tirg = get_irp_irg(i);
ident *irg_id = get_entity_ident(get_irg_entity(tirg));
- if(irg_id == id) {
+ if (irg_id == id) {
irg = tirg;
break;
}
}
- if(irg == NULL) {
+ if (irg == NULL) {
fprintf(stderr, "No graph for function '%s' found\n",
dumpfunction);
exit(1);
}
- dump_ir_block_graph_file(irg, out);
+ dump_ir_graph_file(out, irg);
+ fclose(out);
+ exit(0);
+ }
+
+ if (mode == CompileExportIR) {
fclose(out);
+ ir_export(outname);
exit(0);
}
- gen_firm_finish(asm_out, filename, /*c_mode=*/1,
- have_const_functions);
+ gen_firm_finish(asm_out, filename, have_const_functions);
if (asm_out != out) {
fclose(asm_out);
}
+ } else if (filetype == FILETYPE_IR) {
+ fclose(in);
+ ir_import(filename);
+ goto graph_built;
} else if (filetype == FILETYPE_PREPROCESSED_ASSEMBLER) {
copy_file(asm_out, in);
if (in == preprocessed_in) {
int pp_result = pclose(preprocessed_in);
if (pp_result != EXIT_SUCCESS) {
+ /* remove output in error case */
+ if (out != stdout)
+ unlink(outname);
return pp_result;
}
}
- if(asm_out != out) {
+ if (asm_out != out) {
fclose(asm_out);
}
}
if (filetype == FILETYPE_PREPROCESSED_ASSEMBLER) {
char temp[1024];
const char *filename_o;
- if(mode == CompileAssemble) {
+ if (mode == CompileAssemble) {
fclose(out);
filename_o = outname;
} else {
file->type = filetype;
}
- if (result != EXIT_SUCCESS)
+ if (result != EXIT_SUCCESS) {
+ if (out != stdout)
+ unlink(outname);
return result;
+ }
/* link program file */
- if(mode == CompileAssembleLink) {
+ if (mode == CompileAssembleLink) {
obstack_1grow(&ldflags_obst, '\0');
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)
char *commandline = obstack_finish(&file_obst);
- if(verbose) {
+ if (verbose) {
puts(commandline);
}
int err = system(commandline);
- if(err != EXIT_SUCCESS) {
+ if (err != EXIT_SUCCESS) {
fprintf(stderr, "linker reported an error\n");
exit(1);
}
}
+ if (do_timing)
+ timer_term(stderr);
+
obstack_free(&cppflags_obst, NULL);
obstack_free(&ldflags_obst, NULL);
obstack_free(&file_obst, NULL);
+ exit_mangle();
exit_ast2firm();
exit_parser();
exit_ast();