/* 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;
+ }
+}
+
/*************************************************************
* _ _ __ _ _
* (_) | | / _| | | | |
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);
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 */
*/
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);
}
* 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");
}
/**
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_ */
#include "entity.h"
#include "irprog.h"
+#include "ia32_emitter.h"
#include "ia32_gen_decls.h"
/************************************************************************/
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
*/
};
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;
+ }
}
/*
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);
}
}
}
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);
}
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);
}