Commit 1c04590f authored by Michael Beck's avatar Michael Beck
Browse files

add code for MinGW gas support

parent 9d1c98b6
......@@ -38,6 +38,61 @@
/* 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");
}
/**
......
......@@ -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_ */
......@@ -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);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment