add code for MinGW gas support
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 6 Apr 2006 16:47:27 +0000 (16:47 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 6 Apr 2006 16:47:27 +0000 (16:47 +0000)
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_emitter.h
ir/be/ia32/ia32_gen_decls.c

index d2fab3b..0153117 100644 (file)
 /* global arch_env for lc_printf functions */
 static const arch_env_t *arch_env = NULL;
 
+/** by default, we generate assembler code for the Linux gas */
+asm_flavour_t asm_flavour = ASM_LINUX_GAS;
+
+/**
+ * Switch to a new section
+ */
+void ia32_switch_section(FILE *F, section_t sec) {
+       static section_t curr_sec = NO_SECTION;
+  static const char *text[ASM_MAX][SECTION_MAX] = {
+               {
+                       ".section\t.text", ".section\t.data", ".section\t.rodata", ".section\t.text"
+               },
+               {
+                       ".section\t.text", ".section\t.data", ".section .rdata,\"dr\"", ".section\t.text"
+               }
+       };
+
+       if (curr_sec == sec)
+               return;
+
+       curr_sec = sec;
+       switch (sec) {
+
+       case NO_SECTION:
+               break;
+
+       case SECTION_TEXT:
+       case SECTION_DATA:
+       case SECTION_RODATA:
+       case SECTION_COMMON:
+               fprintf(F, "\t%s\n", text[asm_flavour][sec]);
+       }
+}
+
+static void ia32_dump_function_object(FILE *F, const char *name)
+{
+       switch (asm_flavour) {
+       case ASM_LINUX_GAS:
+               fprintf(F, "\t.type\t%s, @function\n", name);
+               break;
+       case ASM_MINGW_GAS:
+               fprintf(F, "\t.def\t%s;\t.scl\t2;\t.type\t32;\t.endef\n", name);
+               break;
+       }
+}
+
+static void ia32_dump_function_size(FILE *F, const char *name)
+{
+       switch (asm_flavour) {
+       case ASM_LINUX_GAS:
+               fprintf(F, "\t.size\t%s, .-%s\n", name, name);
+               break;
+       }
+}
+
 /*************************************************************
  *             _       _    __   _          _
  *            (_)     | |  / _| | |        | |
@@ -941,7 +996,7 @@ static void emit_ia32_SwitchJmp(const ir_node *irn, ia32_emit_env_t *emit_env) {
                snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* get jump table entry as target */");
                IA32_DO_EMIT(irn);
 
-               fprintf(F, "\t.section\t.rodata\n");
+               ia32_switch_section(F, SECTION_RODATA);
                fprintf(F, "\t.align 4\n");
 
                fprintf(F, "%s:\n", tbl.label);
@@ -961,8 +1016,7 @@ static void emit_ia32_SwitchJmp(const ir_node *irn, ia32_emit_env_t *emit_env) {
                        snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* case %d */", last_value);
                        IA32_DO_EMIT(irn);
                }
-
-               fprintf(F, "\n\t.text\n\n");
+               ia32_switch_section(F, SECTION_TEXT);
        }
        else {
                /* one jump is enough */
@@ -1441,13 +1495,14 @@ static void ia32_gen_block(ir_node *block, void *env) {
  */
 static void ia32_emit_func_prolog(FILE *F, ir_graph *irg) {
        entity     *irg_ent  = get_irg_entity(irg);
-       const char *irg_name = get_entity_name(irg_ent);
+       const char *irg_name = get_entity_ld_name(irg_ent);
 
-       fprintf(F, "\t.section\t.text\n");
+       fprintf(F, "\n");
+       ia32_switch_section(F, SECTION_TEXT);
        if (get_entity_visibility(irg_ent) == visibility_external_visible) {
                fprintf(F, ".globl %s\n", irg_name);
        }
-       fprintf(F, "\t.type\t%s, @function\n", irg_name);
+       ia32_dump_function_object(F, irg_name);
        fprintf(F, "%s:\n", irg_name);
 }
 
@@ -1455,10 +1510,11 @@ static void ia32_emit_func_prolog(FILE *F, ir_graph *irg) {
  * Emits code for function end
  */
 static void ia32_emit_func_epilog(FILE *F, ir_graph *irg) {
-       const char *irg_name = get_entity_name(get_irg_entity(irg));
+       const char *irg_name = get_entity_ld_name(get_irg_entity(irg));
 
        fprintf(F, "\tret\n");
-       fprintf(F, "\t.size\t%s, .-%s\n\n", irg_name, irg_name);
+       ia32_dump_function_size(F, irg_name);
+       fprintf(F, "\n");
 }
 
 /**
index 41416f4..0a4ae0f 100644 (file)
@@ -30,4 +30,29 @@ const char *get_ia32_in_reg_name(ir_node *irn, int pos);
 
 void ia32_gen_routine(FILE *F, ir_graph *irg, const ia32_code_gen_t *cg);
 
+/**
+ * Sections.
+ */
+typedef enum section_t {
+       NO_SECTION     = -1,  /**< no section selected yet. */
+       SECTION_TEXT   = 0,   /**< text section */
+       SECTION_DATA   = 1,   /**< data section */
+       SECTION_RODATA = 2,   /**< rodata section */
+       SECTION_COMMON = 3,   /**< common section */
+       SECTION_MAX    = 4
+} section_t;
+
+/**
+ * Switch to a new section.
+ */
+void ia32_switch_section(FILE *f, section_t sec);
+
+typedef enum asm_flavour_t {
+       ASM_LINUX_GAS = 0,  /**< Linux gas */
+       ASM_MINGW_GAS = 1,  /**< MinGW gas */
+       ASM_MAX       = 2
+} asm_flavour_t;
+
+extern asm_flavour_t asm_flavour;
+
 #endif /* _IA32_EMITTER_H_ */
index 5646266..9e6d3da 100644 (file)
@@ -16,6 +16,7 @@
 #include "entity.h"
 #include "irprog.h"
 
+#include "ia32_emitter.h"
 #include "ia32_gen_decls.h"
 
 /************************************************************************/
@@ -53,6 +54,17 @@ static unsigned highest_bit(unsigned v)
        return res;
 }
 
+static void ia32_dump_comm(struct obstack *obst, const char *name, int size, int align) {
+       switch (asm_flavour) {
+       case ASM_LINUX_GAS:
+               obstack_printf(obst, "\t.comm\t%s,%d,%d\n", name, size, align);
+               break;
+       case ASM_MINGW_GAS:
+               obstack_printf(obst, "\t.comm\t%s,%d\n", name, size);
+               break;
+       }
+}
+
 /*
  * output the alignment
  */
@@ -309,8 +321,12 @@ struct arr_info {
 };
 
 static void dump_object_size(struct obstack *obst, const char *name, int size) {
-       obstack_printf(obst, "\t.type\t%s,@object\n", name);
-       obstack_printf(obst, "\t.size\t%s,%d\n", name, size);
+       switch (asm_flavour) {
+       case ASM_LINUX_GAS:
+               obstack_printf(obst, "\t.type\t%s,@object\n", name);
+               obstack_printf(obst, "\t.size\t%s,%d\n", name, size);
+               break;
+       }
 }
 
 /*
@@ -499,7 +515,7 @@ static void dump_global(struct obstack *rdata_obstack, struct obstack *data_obst
                        if (align < 1)
                                align = 1;
 
-                       obstack_printf(comm_obstack, "\t.comm\t%s,%d,%d\n", ld_name, (get_type_size_bits(ty) + 7) >> 3, align);
+                       ia32_dump_comm(comm_obstack, ld_name, (get_type_size_bits(ty) + 7) >> 3, align);
                }
        }
 }
@@ -532,7 +548,7 @@ void ia32_gen_decls(FILE *out) {
        size = obstack_object_size(&data);
        cp   = obstack_finish(&data);
        if (size > 0) {
-               fprintf(out, "\t.data\n");
+               ia32_switch_section(out, SECTION_DATA);
                fwrite(cp, 1, size, out);
        }
 
@@ -546,7 +562,7 @@ void ia32_gen_decls(FILE *out) {
        size = obstack_object_size(&comm);
        cp   = obstack_finish(&comm);
        if (size > 0) {
-               fprintf(out, "\t.text\n");
+               ia32_switch_section(out, SECTION_COMMON);
                fwrite(cp, 1, size, out);
        }