#include "driver/firm_opt.h"
#include "driver/firm_cmdline.h"
#include "driver/firm_timing.h"
+#include "driver/firm_os.h"
#include "adt/error.h"
+#include "adt/strutil.h"
#include "wrappergen/write_fluffy.h"
-#include "wrappergen/write_caml.h"
#include "wrappergen/write_jna.h"
#include "revision.h"
#include "warning.h"
#ifndef PREPROCESSOR
#ifndef __WIN32__
-#define PREPROCESSOR "gcc -E -m32 -U__STRICT_ANSI__"
+#define PREPROCESSOR "gcc -E -U__STRICT_ANSI__"
#else
-#define PREPROCESSOR "cpp -m32 -U__STRICT_ANSI__"
+#define PREPROCESSOR "cpp -U__STRICT_ANSI__"
#endif
#endif
#ifndef LINKER
-#define LINKER "gcc -m32"
+#define LINKER "gcc"
#endif
#ifndef ASSEMBLER
-#ifdef __APPLE__
-#define ASSEMBLER "gcc -m32 -c -xassembler"
-#else
-#define ASSEMBLER "as --32"
-#endif
+#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;
-bool use_builtins = false;
-bool have_const_functions = false;
-atomic_type_kind_t wchar_atomic_kind = ATOMIC_TYPE_INT;
+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;
+atomic_type_kind_t wchar_atomic_kind = ATOMIC_TYPE_INT;
+unsigned force_long_double_size = 0;
+bool enable_main_collect2_hack = false;
+bool freestanding = false;
/* to switch on printing of implicit casts */
extern bool print_implicit_casts;
/* to switch on printing of parenthesis to indicate operator precedence */
extern bool print_parenthesis;
-static int verbose;
-static struct obstack cppflags_obst, ldflags_obst;
-static char dep_target[1024];
-static const char *outname;
+static machine_triple_t *target_machine;
+static const char *target_triple;
+static int verbose;
+static struct obstack cppflags_obst;
+static struct obstack ldflags_obst;
+static struct obstack asflags_obst;
+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++) */
assert(obstack_object_size(&cppflags_obst) == 0);
const char *preprocessor = getenv("CPARSER_PP");
- if (preprocessor == NULL)
- preprocessor = PREPROCESSOR;
+ if (preprocessor != NULL) {
+ obstack_printf(&cppflags_obst, "%s ", preprocessor);
+ } else {
+ if (target_triple != NULL)
+ obstack_printf(&cppflags_obst, "%s-", target_triple);
+ obstack_printf(&cppflags_obst, PREPROCESSOR);
+ }
- obstack_printf(&cppflags_obst, "%s ", preprocessor);
switch (filetype) {
case FILETYPE_C:
add_flag(&cppflags_obst, "-std=c99");
}
}
add_flag(&cppflags_obst, fname);
-
obstack_1grow(&cppflags_obst, '\0');
- char *buf = obstack_finish(&cppflags_obst);
+
+ char *commandline = obstack_finish(&cppflags_obst);
if (verbose) {
- puts(buf);
+ puts(commandline);
}
-
- FILE *f = popen(buf, "r");
+ FILE *f = popen(commandline, "r");
if (f == NULL) {
fprintf(stderr, "invoking preprocessor failed\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
-
/* we don't really need that anymore */
- obstack_free(&cppflags_obst, buf);
+ obstack_free(&cppflags_obst, commandline);
return f;
}
static void assemble(const char *out, const char *in)
{
- char buf[65536];
+ obstack_1grow(&asflags_obst, '\0');
+ const char *flags = obstack_finish(&asflags_obst);
const char *assembler = getenv("CPARSER_AS");
- if (assembler == NULL)
- assembler = ASSEMBLER;
+ if (assembler != NULL) {
+ obstack_printf(&asflags_obst, "%s", assembler);
+ } else {
+ if (target_triple != NULL)
+ obstack_printf(&asflags_obst, "%s-", target_triple);
+ obstack_printf(&asflags_obst, "%s", ASSEMBLER);
+ }
+ if (flags[0] != '\0')
+ obstack_printf(&asflags_obst, " %s", flags);
+
+ obstack_printf(&asflags_obst, " %s -o %s", in, out);
+ obstack_1grow(&asflags_obst, '\0');
- snprintf(buf, sizeof(buf), "%s %s -o %s", assembler, in, out);
+ char *commandline = obstack_finish(&asflags_obst);
if (verbose) {
- puts(buf);
+ puts(commandline);
}
-
- int err = system(buf);
- if (err != 0) {
+ int err = system(commandline);
+ if (err != EXIT_SUCCESS) {
fprintf(stderr, "assembler reported an error\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
+ obstack_free(&asflags_obst, commandline);
}
static void print_file_name(const char *file)
/* construct commandline */
const char *linker = getenv("CPARSER_LINK");
- if (linker == NULL)
- linker = LINKER;
+ if (linker != NULL) {
+ obstack_printf(&ldflags_obst, "%s ", linker);
+ } else {
+ if (target_triple != NULL)
+ obstack_printf(&ldflags_obst, "%s-", target_triple);
+ obstack_printf(&ldflags_obst, "%s ", 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);
+ exit(EXIT_FAILURE);
}
+ obstack_free(&ldflags_obst, commandline);
}
static const char *try_dir(const char *dir)
if (fd == -1) {
fprintf(stderr, "couldn't create temporary file: %s\n",
strerror(errno));
- exit(1);
+ exit(EXIT_FAILURE);
}
FILE *out = fdopen(fd, "w");
if (out == NULL) {
fprintf(stderr, "couldn't create temporary file FILE*\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
file_list_entry_t *entry = xmalloc(sizeof(*entry));
temp_files = NULL;
}
-/**
- * Do the necessary lowering for compound parameters.
- */
-void lower_compound_params(void)
-{
- lower_params_t params;
-
- params.def_ptr_alignment = 4;
- params.flags = LF_COMPOUND_RETURN | LF_RETURN_HIDDEN;
- params.hidden_params = ADD_HIDDEN_ALWAYS_IN_FRONT;
- params.find_pointer_type = NULL;
- params.ret_compound_in_regs = NULL;
- lower_calls_with_compounds(¶ms);
-}
-
typedef enum compile_mode_t {
BenchmarkParser,
PreprocessOnly,
LexTest,
PrintAst,
PrintFluffy,
- PrintCaml,
PrintJna
} compile_mode_t;
assert(res);
}
-static void set_option(const char *arg)
-{
- int res = firm_option(arg);
- (void) res;
- assert(res);
-}
-
static void copy_file(FILE *dest, FILE *input)
{
char buf[16384];
}
}
-static inline bool streq(char const* a, char const* b)
-{
- return strcmp(a, b) == 0;
-}
-
-static inline bool strstart(char const* str, char const* start)
-{
- do {
- if (*start == '\0')
- return true;
- } while (*str++ == *start++);
- return false;
-}
-
static FILE *open_file(const char *filename)
{
if (streq(filename, "-")) {
if (in == NULL) {
fprintf(stderr, "Couldn't open '%s': %s\n", filename,
strerror(errno));
- exit(1);
+ exit(EXIT_FAILURE);
}
return in;
return FILETYPE_UNKNOWN;
}
-static void init_os_support(void)
+static bool init_os_support(void)
{
- /* OS option must be set to the backend */
- switch (firm_opt.os_support) {
- case OS_SUPPORT_MINGW:
- set_be_option("ia32-gasmode=mingw");
- wchar_atomic_kind = ATOMIC_TYPE_USHORT;
- break;
- case OS_SUPPORT_LINUX:
- set_be_option("ia32-gasmode=elf");
- break;
- case OS_SUPPORT_MACHO:
- set_be_option("ia32-gasmode=macho");
- set_be_option("ia32-stackalign=4");
- set_be_option("pic");
- break;
+ const char *os = target_machine->operating_system;
+ wchar_atomic_kind = ATOMIC_TYPE_INT;
+ force_long_double_size = 0;
+ enable_main_collect2_hack = false;
+
+ if (strstr(os, "linux") != NULL || strstr(os, "bsd") != NULL
+ || streq(os, "solaris")) {
+ set_create_ld_ident(create_name_linux_elf);
+ } else if (streq(os, "darwin")) {
+ force_long_double_size = 16;
+ set_create_ld_ident(create_name_macho);
+ } else if (strstr(os, "mingw") != NULL || streq(os, "win32")) {
+ wchar_atomic_kind = ATOMIC_TYPE_USHORT;
+ enable_main_collect2_hack = true;
+ set_create_ld_ident(create_name_win32);
+ } else {
+ return false;
}
+
+ return true;
+}
+
+static bool parse_target_triple(const char *arg)
+{
+ machine_triple_t *triple = firm_parse_machine_triple(arg);
+ if (triple == NULL) {
+ fprintf(stderr, "Target-triple is not in the form 'cpu_type-manufacturer-operating_system'\n");
+ return false;
+ }
+ return true;
}
int main(int argc, char **argv)
obstack_init(&cppflags_obst);
obstack_init(&ldflags_obst);
+ obstack_init(&asflags_obst);
obstack_init(&file_obst);
#define GET_ARG_AFTER(def, args) \
if (option[0] == 'O') {
sscanf(&option[1], "%d", &opt_level);
}
- if (strcmp(arg, "-fwin32") == 0) {
- firm_opt.os_support = OS_SUPPORT_MINGW;
- } else if (strcmp(arg, "-fmac") == 0) {
- firm_opt.os_support = OS_SUPPORT_MACHO;
- } else if (strcmp(arg, "-flinux") == 0) {
- firm_opt.os_support = OS_SUPPORT_LINUX;
- }
}
- /* set target/os specific stuff */
- init_os_support();
-
- /* apply optimisation level */
- switch(opt_level) {
- case 0:
- set_option("no-opt");
- break;
- case 1:
- set_option("no-inline");
- break;
- default:
- case 4:
- /* use_builtins = true; */
- /* fallthrough */
- case 3:
- 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");
- break;
+ const char *target = getenv("TARGET");
+ if (target != NULL)
+ parse_target_triple(target);
+ if (target_machine == NULL) {
+ target_machine = firm_get_host_machine();
}
+ choose_optimization_pack(opt_level);
+ setup_firm_for_machine(target_machine);
+ init_os_support();
/* parse rest of options */
- 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;
+ 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) {
const char *arg = argv[i];
if (arg[0] == '-' && arg[1] != '\0') {
GET_ARG_AFTER(opt, "-isystem");
add_flag(&cppflags_obst, "-isystem");
add_flag(&cppflags_obst, "%s", opt);
+#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__CYGWIN__)
+ } else if (streq(option, "pthread")) {
+ /* set flags for the preprocessor */
+ add_flag(&cppflags_obst, "-D_REENTRANT");
+ /* set flags for the linker */
+ add_flag(&ldflags_obst, "-lpthread");
+#endif
} 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 (streq(option, "static")) {
+ add_flag(&ldflags_obst, "-static");
+ } else if (streq(option, "shared")) {
+ add_flag(&ldflags_obst, "-shared");
} else if (option[0] == 'f') {
char const *orig_opt;
GET_ARG_AFTER(orig_opt, "-f");
mode = truth_value ? ParseOnly : CompileAssembleLink;
} else if (streq(opt, "unsigned-char")) {
char_is_signed = !truth_value;
+ } else if (streq(opt, "freestanding")) {
+ freestanding = true;
+ } else if (streq(opt, "hosted")) {
+ freestanding = false;
} else if (truth_value == false &&
streq(opt, "asynchronous-unwind-tables")) {
/* nothing todo, a gcc feature which we don't support
}
} else if (option[0] == 'W') {
if (option[1] == '\0') {
- /* ignore -W, out defaults are already quiet verbose */
+ /* ignore -W, our defaults are already quite verbose */
} else if (strstart(option + 1, "p,")) {
// pass options directly to the preprocessor
const char *opt;
char arch_opt[64];
GET_ARG_AFTER(opt, "-m");
- if (strstart(opt, "arch=")) {
+ if (strstart(opt, "target=")) {
+ GET_ARG_AFTER(opt, "-mtarget=");
+ if (!parse_target_triple(opt)) {
+ argument_errors = true;
+ } else {
+ setup_firm_for_machine(target_machine);
+ target_triple = opt;
+ }
+ } else if (strstart(opt, "triple=")) {
+ GET_ARG_AFTER(opt, "-mtriple=");
+ if (!parse_target_triple(opt)) {
+ argument_errors = true;
+ } else {
+ setup_firm_for_machine(target_machine);
+ target_triple = opt;
+ }
+ } else if (strstart(opt, "arch=")) {
GET_ARG_AFTER(opt, "-march=");
snprintf(arch_opt, sizeof(arch_opt), "%s-arch=%s", cpu_arch, opt);
int res = be_parse_arg(arch_opt);
fprintf(stderr, "error: software floatingpoint not supported yet\n");
argument_errors = true;
} else {
- char *endptr;
- long int value = strtol(opt, &endptr, 10);
- if (*endptr != '\0') {
+ long int value = strtol(opt, NULL, 10);
+ if (value == 0) {
fprintf(stderr, "error: wrong option '-m %s'\n", opt);
argument_errors = true;
- }
- if (value != 16 && value != 32 && value != 64) {
+ } else if (value != 16 && value != 32 && value != 64) {
fprintf(stderr, "error: option -m supports only 16, 32 or 64\n");
argument_errors = true;
} else {
machine_size = (unsigned int)value;
+ add_flag(&asflags_obst, "-m%u", machine_size);
+ add_flag(&ldflags_obst, "-m%u", machine_size);
}
}
} else if (streq(option, "pg")) {
print_parenthesis = true;
} else if (streq(option, "print-fluffy")) {
mode = PrintFluffy;
- } else if (streq(option, "print-caml")) {
- mode = PrintCaml;
} else if (streq(option, "print-jna")) {
mode = PrintJna;
+ } else if (streq(option, "jna-limit")) {
+ ++i;
+ if (i >= argc) {
+ fprintf(stderr, "error: "
+ "expected argument after '--jna-limit'\n");
+ argument_errors = true;
+ break;
+ }
+ jna_limit_output(argv[i]);
+ } else if (streq(option, "jna-libname")) {
+ ++i;
+ if (i >= argc) {
+ fprintf(stderr, "error: "
+ "expected argument after '--jna-libname'\n");
+ argument_errors = true;
+ break;
+ }
+ jna_set_libname(argv[i]);
} else if (streq(option, "time")) {
do_timing = true;
} else if (streq(option, "version")) {
print_cparser_version();
- exit(EXIT_SUCCESS);
+ return EXIT_SUCCESS;
} else if (streq(option, "help")) {
print_help(argv[0]);
help_displayed = true;
streq(suffix, "S") ? FILETYPE_ASSEMBLER :
streq(suffix, "a") ? FILETYPE_OBJECT :
streq(suffix, "c") ? FILETYPE_C :
+ streq(suffix, "C") ? FILETYPE_CXX :
streq(suffix, "cc") ? FILETYPE_CXX :
+ streq(suffix, "cp") ? FILETYPE_CXX :
streq(suffix, "cpp") ? FILETYPE_CXX :
+ streq(suffix, "CPP") ? FILETYPE_CXX :
streq(suffix, "cxx") ? FILETYPE_CXX :
+ streq(suffix, "c++") ? FILETYPE_CXX :
+ streq(suffix, "ii") ? FILETYPE_CXX :
streq(suffix, "h") ? FILETYPE_C :
streq(suffix, "ir") ? FILETYPE_IR :
streq(suffix, "o") ? FILETYPE_OBJECT :
if (print_file_name_file != NULL) {
print_file_name(print_file_name_file);
- return 0;
+ return EXIT_SUCCESS;
}
if (files == NULL) {
fprintf(stderr, "error: no input files specified\n");
if (argument_errors) {
usage(argv[0]);
- return 1;
+ return EXIT_FAILURE;
}
- /* 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;
case BenchmarkParser:
case PrintAst:
case PrintFluffy:
- case PrintCaml:
case PrintJna:
case LexTest:
case PreprocessOnly:
if (out == NULL) {
fprintf(stderr, "Couldn't open '%s' for writing: %s\n", outname,
strerror(errno));
- return 1;
+ return EXIT_FAILURE;
}
}
in = open_file(filename);
lextest(in, filename);
fclose(in);
- exit(EXIT_SUCCESS);
+ return EXIT_SUCCESS;
}
FILE *preprocessed_in = NULL;
/* remove output file */
if (out != stdout)
unlink(outname);
- exit(EXIT_FAILURE);
+ return EXIT_FAILURE;
}
}
} 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;
if (irg == NULL) {
fprintf(stderr, "No graph for function '%s' found\n",
dumpfunction);
- exit(1);
+ return EXIT_FAILURE;
}
dump_ir_graph_file(out, irg);
fclose(out);
- exit(0);
+ return EXIT_SUCCESS;
}
if (mode == CompileExportIR) {
fclose(out);
ir_export(outname);
- exit(0);
+ return EXIT_SUCCESS;
}
- gen_firm_finish(asm_out, filename, have_const_functions);
+ gen_firm_finish(asm_out, filename);
if (asm_out != out) {
fclose(asm_out);
}
/* construct commandline */
const char *linker = getenv("CPARSER_LINK");
- if (linker == NULL)
- linker = LINKER;
- obstack_printf(&file_obst, "%s", linker);
+ if (linker != NULL) {
+ obstack_printf(&file_obst, "%s ", linker);
+ } else {
+ if (target_triple != NULL)
+ obstack_printf(&file_obst, "%s-", target_triple);
+ obstack_printf(&file_obst, "%s ", LINKER);
+ }
+
for (file_list_entry_t *entry = files; entry != NULL;
entry = entry->next) {
if (entry->type != FILETYPE_OBJECT)
int err = system(commandline);
if (err != EXIT_SUCCESS) {
fprintf(stderr, "linker reported an error\n");
- exit(1);
+ return EXIT_FAILURE;
}
}
obstack_free(&cppflags_obst, NULL);
obstack_free(&ldflags_obst, NULL);
+ obstack_free(&asflags_obst, NULL);
obstack_free(&file_obst, NULL);
exit_mangle();
exit_types();
exit_tokens();
exit_symbol_table();
- return 0;
+ return EXIT_SUCCESS;
}