refactor machine/os initialisation part so it can be reused by other frontends
authorMatthias Braun <matze@braunis.de>
Thu, 7 Apr 2011 09:22:46 +0000 (11:22 +0200)
committerMatthias Braun <matze@braunis.de>
Thu, 7 Apr 2011 09:22:46 +0000 (11:22 +0200)
adt/obst.h
adt/xmalloc.c [deleted file]
adt/xmalloc.h [deleted file]
driver/firm_codegen.h
driver/firm_machine.c [new file with mode: 0644]
driver/firm_machine.h [new file with mode: 0644]
driver/firm_opt.c
driver/firm_opt.h
main.c

index 272e4c5..5a815a1 100644 (file)
@@ -17,7 +17,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  * 02111-1307, USA.
  */
-#include "xmalloc.h"
+#include "adt/xmalloc.h"
 #include <libfirm/adt/obstack.h>
 
 #define obstack_chunk_alloc xmalloc
diff --git a/adt/xmalloc.c b/adt/xmalloc.c
deleted file mode 100644 (file)
index 9654bbc..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * This file is part of cparser.
- * 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
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-/*
- * Project:     libFIRM
- * File name:   ir/adt/xmalloc.c
- * Purpose:     Xmalloc --- never failing wrappers for malloc() & friends.
- * Author:      Markus Armbruster
- * Modified by:
- * Created:     1999 by getting from fiasco
- * CVS-ID:      $Id$
- * Copyright:   (c) 1995, 1996 Markus Armbruster
- * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
- */
-
-/* @@@ ToDo: replace this file with the one from liberty.
-   [reimplement xstrdup, ... ] */
-#include <config.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "xmalloc.h"
-#include "error.h"
-#include "util.h"
-
-static inline __attribute__((noreturn))
-void out_of_memory(void)
-{
-       panic("out of memory");
-}
-
-void *xmalloc(size_t size)
-{
-       void *res = malloc(size);
-
-       if (UNLIKELY(res == NULL))
-               out_of_memory();
-
-       return res;
-}
-
-void *xcalloc(size_t num, size_t size)
-{
-       void *res = calloc(num, size);
-
-       if (UNLIKELY(res == NULL))
-               out_of_memory();
-
-       return res;
-}
-
-void *xrealloc(void *ptr, size_t size)
-{
-       void *res = realloc (ptr, size);
-
-       if (UNLIKELY(res == NULL))
-               out_of_memory();
-
-       return res;
-}
-
-char *xstrdup(const char *str)
-{
-       size_t len = strlen(str) + 1;
-       char *res = xmalloc(len);
-       memcpy(res, str, len);
-
-       return res;
-}
diff --git a/adt/xmalloc.h b/adt/xmalloc.h
deleted file mode 100644 (file)
index 29ae5fd..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * This file is part of cparser.
- * 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
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-/**
- * @file
- * @brief     More comfortable allocations.
- * @author    Markus Armbruster
- * @data      1999 by getting from fiasco
- * @version   $Id$
- * Copyright: (c) 1995, 1996 Markus Armbruster
- * Licence:   This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
- */
-#ifndef _XMALLOC_H_
-#define _XMALLOC_H_
-
-#include <stdlib.h>
-#include "config.h"
-
-__attribute__((malloc))
-void *xmalloc(size_t size);
-
-__attribute__((malloc))
-void *xcalloc(size_t num, size_t size);
-
-void *xrealloc(void *ptr, size_t size);
-
-__attribute__((malloc))
-char *xstrdup(const char *str);
-
-#define xfree(ptr)      free(ptr)
-
-#endif
index 5521210..931320a 100644 (file)
@@ -4,4 +4,4 @@
 /* Calls the specified backend. */
 void do_codegen(FILE *out, const char *asm_file_name);
 
-#endif /* FIRM_CODEGEN_H */
+#endif
diff --git a/driver/firm_machine.c b/driver/firm_machine.c
new file mode 100644 (file)
index 0000000..23a2483
--- /dev/null
@@ -0,0 +1,141 @@
+#include <config.h>
+
+#include <assert.h>
+#include <stdbool.h>
+#include "firm_os.h"
+#include "adt/strutil.h"
+#include "adt/xmalloc.h"
+#include <libfirm/firm.h>
+
+static void set_be_option(const char *arg)
+{
+       int res = be_parse_arg(arg);
+       (void) res;
+       assert(res);
+}
+
+/**
+ * Initialize firm codegeneration for a specific operating system.
+ * The argument is the operating system part of a target-triple
+ */
+static bool setup_os_support(const char *os)
+{
+       if (strstr(os, "linux") != NULL || strstr(os, "bsd") != NULL
+                       || streq(os, "solaris")) {
+               set_be_option("ia32-gasmode=elf");
+       } else if (streq(os, "darwin")) {
+               set_be_option("ia32-gasmode=macho");
+               set_be_option("ia32-stackalign=4");
+               set_be_option("pic=true");
+       } else if (strstr(os, "mingw") != NULL || streq(os, "win32")) {
+               set_be_option("ia32-gasmode=mingw");
+       } else {
+               return false;
+       }
+
+       return true;
+}
+
+bool setup_firm_for_machine(const machine_triple_t *machine)
+{
+       const char *cpu = machine->cpu_type;
+
+       if (streq(cpu, "i386")) {
+               set_be_option("isa=ia32");
+               set_be_option("ia32-arch=i386");
+       } else if (streq(cpu, "i486")) {
+               set_be_option("isa=ia32");
+               set_be_option("ia32-arch=i486");
+       } else if (streq(cpu, "i586")) {
+               set_be_option("isa=ia32");
+               set_be_option("ia32-arch=i586");
+       } else if (streq(cpu, "i686")) {
+               set_be_option("isa=ia32");
+               set_be_option("ia32-arch=i686");
+       } else if (streq(cpu, "i786")) {
+               set_be_option("isa=ia32");
+               set_be_option("ia32-arch=pentium4");
+       } else if (streq(cpu, "x86_64")) {
+               set_be_option("isa=amd64");
+       } else if (streq(cpu, "sparc")) {
+               set_be_option("isa=sparc");
+       } else if (streq(cpu, "arm")) {
+               set_be_option("isa=arm");
+       } else {
+               fprintf(stderr, "Unknown cpu '%s' in target-triple\n", cpu);
+               return false;
+       }
+
+       /* process operating system */
+       if (!setup_os_support(machine->operating_system)) {
+               fprintf(stderr, "Unknown operating system '%s' in target-triple\n", machine->operating_system);
+               return false;
+       }
+       return true;
+}
+
+machine_triple_t *firm_get_host_machine(void)
+{
+       machine_triple_t *machine = XMALLOC(machine_triple_t);
+       machine->cpu_type = xstrdup("i386");
+       machine->manufacturer = xstrdup("unknown");
+#if defined(_WIN32) || defined(__CYGWIN__)
+       machine->operating_system = xstrdup("win32");
+#elif defined(__APPLE__)
+       machine->operating_system = xstrdup("darwin");
+#else
+       machine->operating_system = xstrdup("linux");
+#endif
+       return machine;
+}
+
+void firm_free_machine_triple(machine_triple_t *machine)
+{
+       free(machine->cpu_type);
+       free(machine->manufacturer);
+       free(machine->operating_system);
+       free(machine);
+}
+
+machine_triple_t *firm_parse_machine_triple(const char *triple_string)
+{
+       const char *manufacturer = strchr(triple_string, '-');
+       if (manufacturer == NULL) {
+               return NULL;
+       }
+       manufacturer += 1;
+
+       const char *os = strchr(manufacturer, '-');
+       if (os == NULL) {
+               return false;
+       }
+       os += 1;
+
+       /* Note: Triples are more or less defined by what the config.guess and
+        * config.sub scripts from GNU autoconf emit. We have to lookup there what
+        * triples are possible */
+
+       const char *cpu = triple_string;
+
+       machine_triple_t *triple = XMALLOCZ(machine_triple_t);
+
+       size_t cpu_type_len = manufacturer-cpu+1;
+       triple->cpu_type = XMALLOCN(char, cpu_type_len);
+       memcpy(triple->cpu_type, cpu, cpu_type_len-1);
+       triple->cpu_type[cpu_type_len-1] = '\0';
+
+       /* process manufacturer, alot of people incorrectly leave out the
+        * manufacturer instead of using unknown- */
+       if (strstart(manufacturer, "linux")) {
+               triple->manufacturer = xstrdup("unknown");
+               os = manufacturer;
+       } else {
+               size_t manufacturer_len = os-manufacturer+1;
+               triple->manufacturer = XMALLOCN(char, manufacturer_len);
+               memcpy(triple->manufacturer, manufacturer, manufacturer_len-1);
+               triple->manufacturer[manufacturer_len-1] = '\0';
+       }
+
+       triple->operating_system = xstrdup(os);
+       return triple;
+}
diff --git a/driver/firm_machine.h b/driver/firm_machine.h
new file mode 100644 (file)
index 0000000..567287d
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef FIRM_OS_H
+#define FIRM_OS_H
+
+#include <stdbool.h>
+
+typedef struct machine_triple_t {
+       char *cpu_type;
+       char *manufacturer;
+       char *operating_system;
+} machine_triple_t;
+
+machine_triple_t *firm_get_host_machine(void);
+
+machine_triple_t *firm_parse_machine_triple(const char *triple_string);
+
+void firm_free_machine_triple(machine_triple_t *triple);
+
+bool setup_firm_for_machine(const machine_triple_t *triple);
+
+#endif
index 8c1a513..1653f00 100644 (file)
@@ -768,6 +768,48 @@ void firm_opt_option_help(void)
        }
 }
 
+static void set_be_option(const char *arg)
+{
+       int res = be_parse_arg(arg);
+       (void) res;
+       assert(res);
+}
+
+static void set_option(const char *arg)
+{
+       int res = firm_option(arg);
+       (void) res;
+       assert(res);
+}
+
+void choose_optimization_pack(int level)
+{
+       /* apply optimisation level */
+       switch(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("fp-vrp");
+               set_option("deconv");
+               set_be_option("omitfp");
+               break;
+       }
+}
+
 /**
  * Do very early initializations
  */
index 97bbba5..4b5192b 100644 (file)
@@ -115,4 +115,14 @@ int firm_opt_option(const char *opt);
 /** print help about optimisations options */
 void firm_opt_option_help(void);
 
-#endif /* FIRM_OPT_H */
+/** Choose an optimization level. (Typically used to interpret the -O compiler
+ * switches) */
+void choose_optimization_pack(int level);
+
+/**
+ * Setup firm to generate code for a specific os.
+ * The parameter should be the OS-part of a machine triple
+ */
+void firm_init_os(const char *os);
+
+#endif
diff --git a/main.c b/main.c
index 58b81bb..ff41e7d 100644 (file)
--- a/main.c
+++ b/main.c
@@ -72,6 +72,7 @@
 #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"
@@ -114,13 +115,14 @@ extern bool print_implicit_casts;
 /* to switch on printing of parenthesis to indicate operator precedence */
 extern bool print_parenthesis;
 
-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;
+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++) */
@@ -570,13 +572,6 @@ static void set_be_option(const char *arg)
        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];
@@ -621,29 +616,22 @@ static filetype_t get_filetype_from_string(const char *string)
        return FILETYPE_UNKNOWN;
 }
 
-/**
- * Initialize firm codegeneration for a specific operating system.
- * The argument is the operating system part of a target-triple */
-static bool set_os_support(const char *os)
+static bool init_os_support(void)
 {
+       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_be_option("ia32-gasmode=elf");
                set_create_ld_ident(create_name_linux_elf);
        } else if (streq(os, "darwin")) {
                force_long_double_size = 16;
-               set_be_option("ia32-gasmode=macho");
-               set_be_option("ia32-stackalign=4");
-               set_be_option("pic=true");
                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_be_option("ia32-gasmode=mingw");
                set_create_ld_ident(create_name_win32);
        } else {
                return false;
@@ -654,65 +642,11 @@ static bool set_os_support(const char *os)
 
 static bool parse_target_triple(const char *arg)
 {
-       const char *manufacturer = strchr(arg, '-');
-       if (manufacturer == NULL) {
+       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;
        }
-       manufacturer += 1;
-
-       const char *os = strchr(manufacturer, '-');
-       if (os == NULL) {
-               fprintf(stderr, "Target-triple is not in the form 'cpu_type-manufacturer-operating_system'\n");
-               return false;
-       }
-       os += 1;
-
-       /* Note: Triples are more or less defined by what the config.guess and
-        * config.sub scripts from GNU autoconf emit. We have to lookup there what
-        * triples are possible */
-
-       /* process cpu type */
-       if (strstart(arg, "i386-")) {
-               be_parse_arg("isa=ia32");
-               be_parse_arg("ia32-arch=i386");
-       } else if (strstart(arg, "i486-")) {
-               be_parse_arg("isa=ia32");
-               be_parse_arg("ia32-arch=i486");
-       } else if (strstart(arg, "i586-")) {
-               be_parse_arg("isa=ia32");
-               be_parse_arg("ia32-arch=i586");
-       } else if (strstart(arg, "i686-")) {
-               be_parse_arg("isa=ia32");
-               be_parse_arg("ia32-arch=i686");
-       } else if (strstart(arg, "i786-")) {
-               be_parse_arg("isa=ia32");
-               be_parse_arg("ia32-arch=pentium4");
-       } else if (strstart(arg, "x86_64")) {
-               be_parse_arg("isa=amd64");
-       } else if (strstart(arg, "sparc-")) {
-               be_parse_arg("isa=sparc");
-       } else if (strstart(arg, "arm-")) {
-               be_parse_arg("isa=arm");
-       } else {
-               fprintf(stderr, "Unknown cpu in triple '%s'\n", arg);
-               return false;
-       }
-
-       /* process manufacturer, alot of people incorrectly leave out the
-        * manufacturer instead of using unknown- */
-       if (strstart(manufacturer, "linux")) {
-               os = manufacturer;
-               manufacturer = "unknown-";
-       }
-
-       /* process operating system */
-       if (!set_os_support(os)) {
-               fprintf(stderr, "Unknown operating system '%s' in triple '%s'\n", os, arg);
-               return false;
-       }
-
-       target_triple = arg;
        return true;
 }
 
@@ -776,43 +710,15 @@ int main(int argc, char **argv)
                }
        }
 
-       /* Guess host OS */
-#if defined(_WIN32) || defined(__CYGWIN__)
-       set_os_support("win32");
-#elif defined(__APPLE__)
-       set_os_support("darwin");
-#else
-       set_os_support("linux");
-#endif
-
-       /* 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("fp-vrp");
-               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;
@@ -1026,12 +932,20 @@ int main(int argc, char **argv)
                                GET_ARG_AFTER(opt, "-m");
                                if (strstart(opt, "target=")) {
                                        GET_ARG_AFTER(opt, "-mtarget=");
-                                       if (!parse_target_triple(opt))
+                                       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))
+                                       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);