#define ASSEMBLER "gcc -c -xassembler"
#endif
-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;
-atomic_type_kind_t wchar_atomic_kind = ATOMIC_TYPE_INT;
-unsigned long_double_size = 0;
-bool enable_main_collect2_hack = false;
-bool freestanding = false;
+unsigned int c_mode = _C89 | _ANSI | _C99 | _GNUC;
+bool byte_order_big_endian = false;
+bool strict_mode = false;
+bool enable_main_collect2_hack = false;
+bool freestanding = false;
+unsigned architecture_modulo_shift = 0;
+
+static bool char_is_signed = true;
+static atomic_type_kind_t wchar_atomic_kind = ATOMIC_TYPE_INT;
static machine_triple_t *target_machine;
static const char *target_triple;
static int verbose;
-static bool use_builtins;
static struct obstack cppflags_obst;
static struct obstack ldflags_obst;
static struct obstack asflags_obst;
static char dep_target[1024];
static const char *outname;
static bool define_intmax_types;
+static const char *input_encoding;
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_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 {
panic("filename too long");
}
-#include "gen_builtins.h"
-
static translation_unit_t *do_parsing(FILE *const in, const char *const input_name)
{
start_parsing();
- if (use_builtins) {
- lexer_open_buffer(builtins, sizeof(builtins)-1, "<builtin>");
- parse();
- }
-
- lexer_open_stream(in, input_name);
+ input_t *input = input_from_stream(in, input_encoding);
+ lexer_switch_input(input, input_name);
parse();
-
translation_unit_t *unit = finish_parsing();
+ input_free(input);
+
return unit;
}
static void lextest(FILE *in, const char *fname)
{
- lexer_open_stream(in, fname);
+ input_t *input = input_from_stream(in, input_encoding);
+ lexer_switch_input(input, fname);
do {
lexer_next_preprocessing_token();
print_token(stdout, &lexer_token);
putchar('\n');
- } while (lexer_token.type != T_EOF);
+ } while (lexer_token.kind != T_EOF);
+ input_free(input);
}
static void add_flag(struct obstack *obst, const char *format, ...)
return get_atomic_kind_name(type->atomic.akind);
}
-static FILE *preprocess(const char *fname, filetype_t filetype)
+static FILE *preprocess(const char *fname, filetype_t filetype,
+ lang_standard_t standard)
{
static const char *common_flags = NULL;
obstack_printf(&cppflags_obst, PREPROCESSOR);
}
+ char const *lang;
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;
+ case FILETYPE_C: lang = "c"; break;
+ case FILETYPE_CXX: lang = "c++"; break;
+ case FILETYPE_ASSEMBLER: lang = "assembler-with-cpp"; break;
+ default: lang = NULL; break;
+ }
+ if (lang)
+ add_flag(&cppflags_obst, "-x%s", lang);
+
+ char const *std = NULL;
+ switch (standard) {
+ case STANDARD_C89: std = "-std=c89"; break;
+ case STANDARD_C90: std = "-std=iso9899:199409"; break;
+ case STANDARD_C99: std = "-std=c99"; break;
+ case STANDARD_GNU89: std = "-std=gnu89"; break;
+ case STANDARD_GNU99: std = "-std=gnu99"; break;
+ case STANDARD_CXX98: std = "-std=c++98"; break;
+ case STANDARD_GNUXX98: std = "-std=gnu++98"; break;
+ case STANDARD_DEFAULT: panic("invalid standard");
}
+ if (std)
+ add_flag(&cppflags_obst, std);
+
obstack_printf(&cppflags_obst, "%s", common_flags);
/* handle dependency generation */
add_flag(&cppflags_obst, "-MF");
add_flag(&cppflags_obst, dep_target);
if (outname != NULL) {
- add_flag(&cppflags_obst, "-MQ");
- add_flag(&cppflags_obst, outname);
+ add_flag(&cppflags_obst, "-MQ");
+ add_flag(&cppflags_obst, outname);
}
}
add_flag(&cppflags_obst, fname);
const char *revision = ir_get_version_revision();
if (revision[0] != 0) {
- putchar(' ');
+ putchar('-');
fputs(revision, stdout);
}
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
}
+static void print_cparser_version_short(void)
+{
+ puts(cparser_REVISION);
+}
+
static void print_help_basic(const char *argv0)
{
usage(argv0);
put_help("-fmessage-length=LEN", "Ignored (gcc compatibility)");
put_help("-fshort-wchar", "Type \"wchar_t\" is unsigned short instead of int");
put_help("-fshow-column", "Show the column number in diagnostic messages");
+ put_help("-fsigned-char", "Type \"char\" is a signed type");
put_help("-funsigned-char", "Type \"char\" is an unsigned type");
put_help("--ms", "Enable msvc extensions");
put_help("--no-ms", "Disable msvc extensions");
put_help("-w", "Disable all warnings");
put_help("-Wno-trigraphs", "Warn if input contains trigraphs");
put_help("-Wundef", "Warn if an undefined macro is used in an #if");
+ put_help("-Wmissing-include-dirs", "Warn about missing user-specified include directories");
+ put_help("-Wendif-labels", "Warn about stray text after #elif and #endif");
+ put_help("-Winit-self", "Ignored (gcc compatibility)");
+ put_help("-Wformat-y2k", "Ignored (gcc compatibility)");
+ put_help("-Wformat-security", "Ignored (gcc compatibility)");
+ put_help("-Wold-style-declaration", "Ignored (gcc compatibility)");
+ put_help("-Wtype-limits", "Ignored (gcc compatibility)");
print_warning_opt_help();
}
put_help("-ffast-math", "Same as -ffp-fast (gcc compatibility)");
puts("");
puts("\tMost of these options can be used with a no- prefix to disable them");
- puts("\te.g. -fno-signed-char");
+ puts("\te.g. -fno-omit-frame-pointer");
}
static void print_help_linker(void)
{
put_help("-l LIBRARY", "");
put_help("-L PATH", "");
+ put_help("-s", "Do not produce symbol table and relocation information");
put_help("-shared", "Produce a shared library");
put_help("-static", "Produce statically linked binary");
put_help("-Wl,OPTION", "Pass option directly to linker");
typedef enum {
HELP_NONE = 0,
- HELP_BASIC = 1u << 0,
- HELP_PREPROCESSOR = 1u << 1,
- HELP_PARSER = 1u << 2,
- HELP_WARNINGS = 1u << 3,
- HELP_OPTIMIZATION = 1u << 4,
- HELP_CODEGEN = 1u << 5,
- HELP_LINKER = 1u << 6,
- HELP_LANGUAGETOOLS = 1u << 7,
- HELP_DEBUG = 1u << 8,
- HELP_FIRM = 1u << 9,
-
- HELP_ALL = (unsigned)-1
+ HELP_BASIC = 1 << 0,
+ HELP_PREPROCESSOR = 1 << 1,
+ HELP_PARSER = 1 << 2,
+ HELP_WARNINGS = 1 << 3,
+ HELP_OPTIMIZATION = 1 << 4,
+ HELP_CODEGEN = 1 << 5,
+ HELP_LINKER = 1 << 6,
+ HELP_LANGUAGETOOLS = 1 << 7,
+ HELP_DEBUG = 1 << 8,
+ HELP_FIRM = 1 << 9,
+
+ HELP_ALL = -1
} help_sections_t;
static void print_help(const char *argv0, help_sections_t sections)
static bool init_os_support(void)
{
- const char *os = target_machine->operating_system;
wchar_atomic_kind = ATOMIC_TYPE_INT;
enable_main_collect2_hack = false;
define_intmax_types = false;
- if (strstr(os, "linux") != NULL || strstr(os, "bsd") != NULL
- || streq(os, "solaris")) {
+ if (firm_is_unixish_os(target_machine)) {
set_create_ld_ident(create_name_linux_elf);
- } else if (streq(os, "darwin")) {
- long_double_size = 16;
+ } else if (firm_is_darwin_os(target_machine)) {
set_create_ld_ident(create_name_macho);
define_intmax_types = true;
- } else if (strstr(os, "mingw") != NULL || streq(os, "win32")) {
+ } else if (firm_is_windows_os(target_machine)) {
wchar_atomic_kind = ATOMIC_TYPE_USHORT;
enable_main_collect2_hack = true;
set_create_ld_ident(create_name_win32);
return true;
}
-static void setup_target_machine(void)
+static unsigned decide_modulo_shift(unsigned type_size)
+{
+ if (architecture_modulo_shift == 0)
+ return 0;
+ if (type_size < architecture_modulo_shift)
+ return architecture_modulo_shift;
+ return type_size;
+}
+
+static bool is_ia32_cpu(const char *architecture)
+{
+ return streq(architecture, "i386")
+ || streq(architecture, "i486")
+ || streq(architecture, "i586")
+ || streq(architecture, "i686")
+ || streq(architecture, "i786");
+}
+
+static const char *setup_isa_from_tripel(const machine_triple_t *machine)
+{
+ const char *cpu = machine->cpu_type;
+
+ if (is_ia32_cpu(cpu)) {
+ return "ia32";
+ } else if (streq(cpu, "x86_64")) {
+ return "amd64";
+ } else if (streq(cpu, "sparc")) {
+ return "sparc";
+ } else if (streq(cpu, "arm")) {
+ return "arm";
+ } else {
+ fprintf(stderr, "Unknown cpu '%s' in target-triple\n", cpu);
+ return NULL;
+ }
+}
+
+static const char *setup_target_machine(void)
{
if (!setup_firm_for_machine(target_machine))
exit(1);
- const backend_params *be_params = be_get_backend_param();
- if (be_params->long_double_size % 8 != 0) {
- fprintf(stderr, "firm-target long double size is not a multiple of 8, cannot handle this\n");
+ const char *isa = setup_isa_from_tripel(target_machine);
+
+ if (isa == NULL)
exit(1);
+
+ init_os_support();
+
+ return isa;
+}
+
+/**
+ * initialize cparser type properties based on a firm type
+ */
+static void set_typeprops_type(atomic_type_properties_t* props, ir_type *type)
+{
+ props->size = get_type_size_bytes(type);
+ props->alignment = get_type_alignment_bytes(type);
+ props->struct_alignment = props->alignment;
+}
+
+/**
+ * Copy atomic type properties except the integer conversion rank
+ */
+static void copy_typeprops(atomic_type_properties_t *dest,
+ const atomic_type_properties_t *src)
+{
+ dest->size = src->size;
+ dest->alignment = src->alignment;
+ dest->struct_alignment = src->struct_alignment;
+ dest->flags = src->flags;
+}
+
+static void init_types_and_adjust(void)
+{
+ const backend_params *be_params = be_get_backend_param();
+ unsigned machine_size = be_params->machine_size;
+ init_types(machine_size);
+
+ atomic_type_properties_t *props = atomic_type_properties;
+
+ /* adjust types as requested by target architecture */
+ ir_type *type_long_double = be_params->type_long_double;
+ if (type_long_double != NULL) {
+ set_typeprops_type(&props[ATOMIC_TYPE_LONG_DOUBLE], type_long_double);
+ atomic_modes[ATOMIC_TYPE_LONG_DOUBLE] = get_type_mode(type_long_double);
}
- byte_order_big_endian = be_params->byte_order_big_endian;
- machine_size = be_params->machine_size;
- long_double_size = be_params->long_double_size / 8;
+ ir_type *type_long_long = be_params->type_long_long;
+ if (type_long_long != NULL)
+ set_typeprops_type(&props[ATOMIC_TYPE_LONGLONG], type_long_long);
+
+ ir_type *type_unsigned_long_long = be_params->type_unsigned_long_long;
+ if (type_unsigned_long_long != NULL)
+ set_typeprops_type(&props[ATOMIC_TYPE_ULONGLONG], type_unsigned_long_long);
+
+ /* operating system ABI specifics */
+ if (firm_is_darwin_os(target_machine)) {
+ if (machine_size == 32) {
+ props[ATOMIC_TYPE_LONGLONG].struct_alignment = 4;
+ props[ATOMIC_TYPE_ULONGLONG].struct_alignment = 4;
+ props[ATOMIC_TYPE_DOUBLE].struct_alignment = 4;
+ props[ATOMIC_TYPE_LONG_DOUBLE].size = 16;
+ props[ATOMIC_TYPE_LONG_DOUBLE].alignment = 16;
+ props[ATOMIC_TYPE_LONG_DOUBLE].struct_alignment = 16;
+ }
+ } else if (firm_is_windows_os(target_machine)) {
+ if (machine_size == 64) {
+ /* to ease porting of old c-code microsoft decided to use 32bits
+ * even for long */
+ props[ATOMIC_TYPE_LONG] = props[ATOMIC_TYPE_INT];
+ props[ATOMIC_TYPE_ULONG] = props[ATOMIC_TYPE_UINT];
+ }
- init_os_support();
+ /* on windows long double is not supported */
+ props[ATOMIC_TYPE_LONG_DOUBLE] = props[ATOMIC_TYPE_DOUBLE];
+ } else if (firm_is_unixish_os(target_machine)) {
+ if (is_ia32_cpu(target_machine->cpu_type)) {
+ /* System V has a broken alignment for double so we have to add
+ * a hack here */
+ props[ATOMIC_TYPE_DOUBLE].struct_alignment = 4;
+ props[ATOMIC_TYPE_LONGLONG].struct_alignment = 4;
+ props[ATOMIC_TYPE_ULONGLONG].struct_alignment = 4;
+ }
+ }
+
+ /* stuff decided after processing operating system specifics and
+ * commandline flags */
+ if (char_is_signed) {
+ props[ATOMIC_TYPE_CHAR].flags |= ATOMIC_TYPE_FLAG_SIGNED;
+ } else {
+ props[ATOMIC_TYPE_CHAR].flags &= ~ATOMIC_TYPE_FLAG_SIGNED;
+ }
+ /* copy over wchar_t properties (including rank) */
+ props[ATOMIC_TYPE_WCHAR_T] = props[wchar_atomic_kind];
+
+ /* initialize defaults for unsupported types */
+ if (type_long_long == NULL) {
+ copy_typeprops(&props[ATOMIC_TYPE_LONGLONG], &props[ATOMIC_TYPE_LONG]);
+ }
+ if (type_unsigned_long_long == NULL) {
+ copy_typeprops(&props[ATOMIC_TYPE_ULONGLONG],
+ &props[ATOMIC_TYPE_ULONG]);
+ }
+ if (type_long_double == NULL) {
+ copy_typeprops(&props[ATOMIC_TYPE_LONG_DOUBLE],
+ &props[ATOMIC_TYPE_DOUBLE]);
+ }
+
+ /* initialize firm pointer modes */
+ char name[64];
+ unsigned bit_size = machine_size;
+ unsigned modulo_shift = decide_modulo_shift(bit_size);
+
+ snprintf(name, sizeof(name), "p%u", machine_size);
+ ir_mode *ptr_mode = new_reference_mode(name, irma_twos_complement, bit_size, modulo_shift);
+
+ if (machine_size == 16) {
+ set_reference_mode_signed_eq(ptr_mode, mode_Hs);
+ set_reference_mode_unsigned_eq(ptr_mode, mode_Hu);
+ } else if (machine_size == 32) {
+ set_reference_mode_signed_eq(ptr_mode, mode_Is);
+ set_reference_mode_unsigned_eq(ptr_mode, mode_Iu);
+ } else if (machine_size == 64) {
+ set_reference_mode_signed_eq(ptr_mode, mode_Ls);
+ set_reference_mode_unsigned_eq(ptr_mode, mode_Lu);
+ } else {
+ panic("strange machine_size when determining pointer modes");
+ }
+
+ /* Hmm, pointers should be machine size */
+ set_modeP_data(ptr_mode);
+ set_modeP_code(ptr_mode);
+
+ byte_order_big_endian = be_params->byte_order_big_endian;
+ if (be_params->modulo_shift_efficient) {
+ architecture_modulo_shift = machine_size;
+ } else {
+ architecture_modulo_shift = 0;
+ }
}
int main(int argc, char **argv)
{
- firm_early_init();
-
const char *dumpfunction = NULL;
const char *print_file_name_file = NULL;
compile_mode_t mode = CompileAssembleLink;
#define SINGLE_OPTION(ch) (option[0] == (ch) && option[1] == '\0')
+ /* initialize this early because it has to parse options */
+ gen_firm_init();
+
/* early options parsing (find out optimization level and OS) */
for (int i = 1; i < argc; ++i) {
const char *arg = argv[i];
}
}
- const char *target = getenv("TARGET");
- if (target != NULL)
- parse_target_triple(target);
if (target_machine == NULL) {
target_machine = firm_get_host_machine();
}
setup_target_machine();
/* parse rest of options */
- standard = STANDARD_DEFAULT;
+ lang_standard_t standard = STANDARD_DEFAULT;
unsigned features_on = 0;
unsigned features_off = 0;
filetype_t forced_filetype = FILETYPE_AUTODETECT;
if (option[0] == 'o') {
GET_ARG_AFTER(outname, "-o");
} else if (option[0] == 'g') {
- set_be_option("debuginfo=stabs");
- set_be_option("omitfp=no");
+ /* TODO: parse -gX with 0<=x<=3... */
+ set_be_option("debug=frameinfo");
set_be_option("ia32-nooptcc=yes");
} else if (SINGLE_OPTION('c')) {
mode = CompileAssemble;
} else if (SINGLE_OPTION('E')) {
mode = PreprocessOnly;
+ } else if (SINGLE_OPTION('s')) {
+ add_flag(&ldflags_obst, "-s");
} else if (SINGLE_OPTION('S')) {
mode = Compile;
} else if (option[0] == 'O') {
} else if (SINGLE_OPTION('v')) {
verbose = 1;
} else if (SINGLE_OPTION('w')) {
+ add_flag(&cppflags_obst, "-w");
disable_all_warnings();
} else if (option[0] == 'x') {
const char *opt;
if (strstart(orig_opt, "input-charset=")) {
char const* const encoding = strchr(orig_opt, '=') + 1;
- select_input_encoding(encoding);
+ input_encoding = encoding;
} else if (strstart(orig_opt, "align-loops=") ||
strstart(orig_opt, "align-jumps=") ||
strstart(orig_opt, "align-functions=")) {
}
} else if (strstart(orig_opt, "message-length=")) {
/* ignore: would only affect error message format */
+ } else if (streq(orig_opt, "fast-math") ||
+ streq(orig_opt, "fp-fast")) {
+ firm_fp_model = fp_model_fast;
+ } else if (streq(orig_opt, "fp-precise")) {
+ firm_fp_model = fp_model_precise;
+ } else if (streq(orig_opt, "fp-strict")) {
+ firm_fp_model = fp_model_strict;
+ } else if (streq(orig_opt, "help")) {
+ fprintf(stderr, "warning: -fhelp is deprecated\n");
+ help |= HELP_OPTIMIZATION;
} else {
/* -f options which have an -fno- variant */
char const *opt = orig_opt;
opt += 3;
}
- if (streq(opt, "builtins")) {
- use_builtins = truth_value;
- } else if (streq(opt, "diagnostics-show-option")) {
+ if (streq(opt, "diagnostics-show-option")) {
diagnostics_show_option = truth_value;
} else if (streq(opt, "dollars-in-identifiers")) {
allow_dollar_in_symbol = truth_value;
* anyway was deactivated */
} else if (streq(opt, "verbose-asm")) {
/* ignore: we always print verbose assembler */
- } else if (streq(opt, "fast-math") || streq(opt, "fp-fast")) {
- firm_fp_model = fp_model_fast;
- } else if (streq(opt, "fp-precise")) {
- firm_fp_model = fp_model_precise;
- } else if (streq(opt, "fp-strict")) {
- firm_fp_model = fp_model_strict;
} else if (streq(opt, "jump-tables") ||
streq(opt, "expensive-optimizations") ||
streq(opt, "common") ||
streq(opt, "align-loops") ||
streq(opt, "align-jumps") ||
streq(opt, "align-functions") ||
- streq(opt, "PIC")) {
+ streq(opt, "unroll-loops") ||
+ streq(opt, "PIC") ||
+ streq(opt, "stack-protector") ||
+ streq(opt, "stack-protector-all")) {
fprintf(stderr, "ignoring gcc option '-f%s'\n", orig_opt);
- } else if (streq(opt, "help")) {
- fprintf(stderr, "warning: -fhelp is deprecated\n");
- help |= HELP_OPTIMIZATION;
} else {
int res = firm_option(orig_opt);
if (res == 0) {
GET_ARG_AFTER(opt, "-Wl,");
add_flag(&ldflags_obst, "-Wl,%s", opt);
} else if (streq(option + 1, "no-trigraphs")
- || streq(option + 1, "undef")) {
+ || streq(option + 1, "undef")
+ || streq(option + 1, "missing-include-dirs")
+ || streq(option + 1, "endif-labels")) {
add_flag(&cppflags_obst, "%s", arg);
+ } else if (streq(option+1, "init-self")) {
+ /* ignored (same as gcc does) */
+ } else if (streq(option+1, "format-y2k")
+ || streq(option+1, "format-security")
+ || streq(option+1, "old-style-declaration")
+ || streq(option+1, "type-limits")) {
+ /* ignore (gcc compatibility) */
} else {
set_warning_opt(&option[1]);
}
if (!parse_target_triple(opt)) {
argument_errors = true;
} else {
- setup_target_machine();
+ const char *isa = setup_target_machine();
+ strncpy(cpu_arch, isa, sizeof(cpu_arch));
target_triple = opt;
}
} else if (strstart(opt, "triple=")) {
if (!parse_target_triple(opt)) {
argument_errors = true;
} else {
- setup_target_machine();
+ const char *isa = setup_target_machine();
+ strncpy(cpu_arch, isa, sizeof(cpu_arch));
target_triple = opt;
}
} else if (strstart(opt, "arch=")) {
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;
+ add_flag(&ldflags_obst, "-msoft-float");
+ snprintf(arch_opt, sizeof(arch_opt), "%s-fpunit=softfloat", cpu_arch);
+ int res = be_parse_arg(arch_opt);
+ if (res == 0)
+ argument_errors = true;
+ } else if (streq(opt, "sse2")) {
+ /* ignore for now, our x86 backend always uses sse when
+ * sse is requested */
} else {
long int value = strtol(opt, NULL, 10);
if (value == 0) {
fprintf(stderr, "error: option -m supports only 16, 32 or 64\n");
argument_errors = true;
} else {
+ unsigned machine_size = (unsigned)value;
+ /* TODO: choose/change backend based on this */
add_flag(&cppflags_obst, "-m%u", machine_size);
add_flag(&asflags_obst, "-m%u", machine_size);
add_flag(&ldflags_obst, "-m%u", machine_size);
- /* TODO: choose/change backend based on this */
}
}
} else if (streq(option, "pg")) {
set_be_option("gprof");
add_flag(&ldflags_obst, "-pg");
- } else if (streq(option, "pedantic") ||
- streq(option, "ansi")) {
+ } else if (streq(option, "ansi")) {
+ add_flag(&cppflags_obst, "-ansi");
+ } else if (streq(option, "pedantic")) {
fprintf(stderr, "warning: ignoring gcc option '%s'\n", arg);
} else if (strstart(option, "std=")) {
const char *const o = &option[4];
(fprintf(stderr, "warning: ignoring gcc option '%s'\n", arg), standard);
} else if (streq(option, "version")) {
print_cparser_version();
+ return EXIT_SUCCESS;
+ } else if (streq(option, "dumpversion")) {
+ /* gcc compatibility option */
+ print_cparser_version_short();
+ return EXIT_SUCCESS;
} else if (strstart(option, "print-file-name=")) {
GET_ARG_AFTER(print_file_name_file, "-print-file-name=");
} else if (option[0] == '-') {
mode = CompileDump;
} else if (streq(option, "export-ir")) {
mode = CompileExportIR;
+ } else if (streq(option, "unroll-loops")) {
+ /* ignore (gcc compatibility) */
} else {
fprintf(stderr, "error: unknown argument '%s'\n", arg);
argument_errors = true;
set_be_option("profileuse");
}
- gen_firm_init();
init_symbol_table();
- init_types();
+ init_types_and_adjust();
init_typehash();
init_basic_types();
+ if (wchar_atomic_kind == ATOMIC_TYPE_INT)
+ init_wchar_types(type_int);
+ else if (wchar_atomic_kind == ATOMIC_TYPE_USHORT)
+ init_wchar_types(type_short);
+ else
+ panic("unexpected wchar type");
init_lexer();
init_ast();
init_parser();
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;
- filetype_t filetype = file->type;
+ char asm_tempfile[1024];
+ const char *filename = file->name;
+ filetype_t filetype = file->type;
+ lang_standard_t file_standard = standard;
if (filetype == FILETYPE_OBJECT)
continue;
+ if (file_standard == STANDARD_DEFAULT) {
+ switch (filetype) {
+ case FILETYPE_C:
+ case FILETYPE_PREPROCESSED_C:
+ file_standard = STANDARD_GNU99;
+ break;
+ case FILETYPE_CXX:
+ case FILETYPE_PREPROCESSED_CXX:
+ file_standard = STANDARD_GNUXX98;
+ break;
+ default:
+ break;
+ }
+ }
FILE *in = NULL;
if (mode == LexTest) {
if (in != NULL)
panic("internal compiler error: in for preprocessor != NULL");
- preprocessed_in = preprocess(filename, filetype);
+ preprocessed_in = preprocess(filename, filetype,
+ file_standard);
if (mode == PreprocessOnly) {
copy_file(out, preprocessed_in);
int pp_result = pclose(preprocessed_in);
/* preprocess and compile */
if (filetype == FILETYPE_PREPROCESSED_C) {
char const* invalid_mode;
- switch (standard) {
- case STANDARD_ANSI:
- case STANDARD_C89: c_mode = _C89; break;
- /* 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;
+ switch (file_standard) {
+ case STANDARD_C89: c_mode = _C89; break;
+ /* 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;
default_c_warn:
- fprintf(stderr,
- "warning: command line option \"-std=%s\" is not valid for C\n",
- invalid_mode);
- /* FALLTHROUGH */
- case STANDARD_DEFAULT:
- case STANDARD_GNU99: c_mode = _C89 | _C99 | _GNUC; break;
-
- case STANDARD_CXX98: invalid_mode = "c++98"; goto default_c_warn;
- case STANDARD_GNUXX98: invalid_mode = "gnu98"; goto default_c_warn;
+ fprintf(stderr,
+ "warning: command line option \"-std=%s\" is not valid for C\n",
+ invalid_mode);
+ /* FALLTHROUGH */
+ case STANDARD_GNU99: c_mode = _C89 | _C99 | _GNUC; break;
+
+ case STANDARD_CXX98: invalid_mode = "c++98"; goto default_c_warn;
+ case STANDARD_GNUXX98: invalid_mode = "gnu98"; goto default_c_warn;
+ case STANDARD_DEFAULT: panic("invalid standard");
}
goto do_parsing;
} else if (filetype == FILETYPE_PREPROCESSED_CXX) {
char const* invalid_mode;
- switch (standard) {
- case STANDARD_C89: invalid_mode = "c89"; goto default_cxx_warn;
- case STANDARD_C90: invalid_mode = "c90"; goto default_cxx_warn;
- case STANDARD_C99: invalid_mode = "c99"; goto default_cxx_warn;
- case STANDARD_GNU89: invalid_mode = "gnu89"; goto default_cxx_warn;
- case STANDARD_GNU99: invalid_mode = "gnu99"; goto default_cxx_warn;
+ switch (file_standard) {
+ case STANDARD_C89: invalid_mode = "c89"; goto default_cxx_warn;
+ case STANDARD_C90: invalid_mode = "c90"; goto default_cxx_warn;
+ case STANDARD_C99: invalid_mode = "c99"; goto default_cxx_warn;
+ case STANDARD_GNU89: invalid_mode = "gnu89"; goto default_cxx_warn;
+ case STANDARD_GNU99: invalid_mode = "gnu99"; goto default_cxx_warn;
- case STANDARD_ANSI:
- case STANDARD_CXX98: c_mode = _CXX; break;
+ case STANDARD_CXX98: c_mode = _CXX; break;
default_cxx_warn:
- fprintf(stderr,
- "warning: command line option \"-std=%s\" is not valid for C++\n",
- invalid_mode);
- case STANDARD_DEFAULT:
- case STANDARD_GNUXX98: c_mode = _CXX | _GNUC; break;
+ fprintf(stderr,
+ "warning: command line option \"-std=%s\" is not valid for C++\n",
+ invalid_mode);
+ case STANDARD_GNUXX98: c_mode = _CXX | _GNUC; break;
+ case STANDARD_DEFAULT: panic("invalid standard");
}
do_parsing:
if (already_constructed_firm) {
panic("compiling multiple files/translation units not possible");
}
+ init_implicit_optimizations();
translation_unit_to_firm(unit);
already_constructed_firm = true;
timer_pop(t_construct);
}
if (mode == CompileExportIR) {
- fclose(out);
- ir_export(outname);
+ ir_export_file(out);
+ if (ferror(out) != 0) {
+ fprintf(stderr, "Error while writing to output\n");
+ return EXIT_FAILURE;
+ }
return EXIT_SUCCESS;
}
- gen_firm_finish(asm_out, filename);
+ generate_code(asm_out, filename);
if (asm_out != out) {
fclose(asm_out);
}
} else if (filetype == FILETYPE_IR) {
fclose(in);
- ir_import(filename);
+ int res = ir_import(filename);
+ if (res != 0) {
+ fprintf(stderr, "Firm-Program import failed\n");
+ return EXIT_FAILURE;
+ }
goto graph_built;
} else if (filetype == FILETYPE_PREPROCESSED_ASSEMBLER) {
copy_file(asm_out, in);
obstack_free(&asflags_obst, NULL);
obstack_free(&file_obst, NULL);
+ gen_firm_finish();
exit_mangle();
exit_ast2firm();
exit_parser();