From: Matthias Braun Date: Sun, 30 Mar 2008 14:24:24 +0000 (+0000) Subject: - cleanup and rewrite some of the dbgout stuff (no passing around of handles anymore) X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=379fd05b0fb269dd9b9105810de1ce565b18e446;p=libfirm - cleanup and rewrite some of the dbgout stuff (no passing around of handles anymore) - port stabs debug output to beemitter - support Mach-O in begnuas - cleanups [r18292] --- diff --git a/ir/be/arm/arm_emitter.c b/ir/be/arm/arm_emitter.c index 529407046..7a3affed7 100644 --- a/ir/be/arm/arm_emitter.c +++ b/ir/be/arm/arm_emitter.c @@ -49,6 +49,7 @@ #include "../beblocksched.h" #include "../beirg_t.h" #include "../begnuas.h" +#include "../be_dbgout.h" #include "arm_emitter.h" #include "gen_arm_emitter.h" @@ -985,40 +986,6 @@ static void arm_register_emitters(void) { #undef SILENCE } -static const char *last_name = NULL; -static unsigned last_line = -1; -static unsigned num = -1; - -/** - * Emit the debug support for node node. - */ -static void arm_emit_dbg(const ir_node *irn) { - dbg_info *db = get_irn_dbg_info(irn); - unsigned lineno; - const char *fname = ir_retrieve_dbg_info(db, &lineno); - - if (! cg->birg->main_env->options->stabs_debug_support) - return; - - if (fname) { - if (last_name != fname) { - last_line = -1; - be_dbg_include_begin(cg->birg->main_env->db_handle, fname); - last_name = fname; - } - if (last_line != lineno) { - char name[64]; - - snprintf(name, sizeof(name), ".LM%u", ++num); - last_line = lineno; - be_dbg_line(cg->birg->main_env->db_handle, lineno, name); - be_emit_string(name); - be_emit_cstring(":\n"); - be_emit_write_line(); - } - } -} - /** * Emits code for a node. */ @@ -1027,7 +994,7 @@ static void arm_emit_node(const ir_node *irn) { if (op->ops.generic) { emit_func *emit = (emit_func *)op->ops.generic; - arm_emit_dbg(irn); + be_dbg_set_dbg_info(get_irn_dbg_info(irn)); (*emit)(irn); } else { be_emit_cstring("\t/* TODO */"); @@ -1097,7 +1064,7 @@ static void arm_gen_block(ir_node *block, ir_node *prev_block) { ir_node *irn; arm_emit_block_header(block, prev_block); - arm_emit_dbg(block); + be_dbg_set_dbg_info(get_irn_dbg_info(block)); sched_foreach(block, irn) { arm_emit_node(irn); } diff --git a/ir/be/be_dbgout.h b/ir/be/be_dbgout.h index d7ca7c04f..9bf8faac2 100644 --- a/ir/be/be_dbgout.h +++ b/ir/be/be_dbgout.h @@ -27,86 +27,32 @@ #ifndef FIRM_BE_BE_DBGOUT_H #define FIRM_BE_BE_DBGOUT_H -#include "obst.h" -#include "beabi_t.h" +#include "beabi.h" -typedef struct dbg_handle dbg_handle; - -/** - * Debug operations. - */ -typedef struct debug_ops { - /** close the stabs handler. */ - void (*close)(dbg_handle *handle); - - /** start a new source object (compilation unit) */ - void (*so)(dbg_handle *handle, const char *filename); - - /** start an include file */ - void (*include_begin)(dbg_handle *handle, const char *filename); - - /** end an include file */ - void (*include_end)(dbg_handle *handle); - - /** Main Program */ - void (*main_program)(dbg_handle *handle); - - /** dumps the stabs for a method begin */ - void (*method_begin)(dbg_handle *handle, ir_entity *ent, const be_stack_layout_t *layout); - - /** dumps the stabs for a method end */ - void (*method_end)(dbg_handle *handle); - - /** dumps a line number */ - void (*line)(dbg_handle *handle, unsigned lineno, const char *address); - - /** dump types */ - void (*types)(dbg_handle *handle); - - /** dump a variable in the global type */ - void (*variable)(dbg_handle *h, struct obstack *obst, ir_entity *ent); - -} debug_ops; - -/** The base class of all debug implementations. */ -struct dbg_handle { - const debug_ops *ops; -}; +/* initialize and open debug handle */ +void be_dbg_open(void); /** close a debug handler. */ -void be_dbg_close(dbg_handle *handle); +void be_dbg_close(void); /** start a new source object (compilation unit) */ -void be_dbg_so(dbg_handle *handle, const char *filename); - -/** start an include file */ -void be_dbg_include_begin(dbg_handle *handle, const char *filename); - -/** end an include file */ -void be_dbg_include_end(dbg_handle *handle); +void be_dbg_so(const char *filename); /** Main program */ -void be_dbg_main_program(dbg_handle *handle); +void be_dbg_main_program(void); /** debug for a method begin */ -void be_dbg_method_begin(dbg_handle *handle, ir_entity *ent, const be_stack_layout_t *layout); +void be_dbg_method_begin(ir_entity *ent, const be_stack_layout_t *layout); /** debug for a method end */ -void be_dbg_method_end(dbg_handle *handle); - -/** debug for line number */ -void be_dbg_line(dbg_handle *handle, unsigned lineno, const char *address); +void be_dbg_method_end(void); /** dump types */ -void be_dbg_types(dbg_handle *handle); +void be_dbg_types(void); /** dump a variable in the global type */ -void be_dbg_variable(dbg_handle *handle, struct obstack *obst, ir_entity *ent); - -/** Opens the NULL handler: no debug support. */ -dbg_handle *be_nulldbg_open(void); +void be_dbg_variable(struct obstack *obst, ir_entity *ent); -/** Opens a stabs handler. */ -dbg_handle *be_stabs_open(FILE *out); +void be_dbg_set_dbg_info(dbg_info *dbgi); -#endif /* FIRM_BE_BE_DBGOUT_H */ +#endif diff --git a/ir/be/be_dbgout_t.h b/ir/be/be_dbgout_t.h new file mode 100644 index 000000000..7acf77eee --- /dev/null +++ b/ir/be/be_dbgout_t.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + +/** + * @file + * @brief Debug output support. + * @author Michael Beck + * @date 11.9.2006 + * @version $Id: be_dbgout.h 17143 2008-01-02 20:56:33Z beck $ + */ +#ifndef FIRM_BE_BE_DBGOUT_T_H +#define FIRM_BE_BE_DBGOUT_T_H + +#include "obst.h" +#include "beabi_t.h" +#include "firm_types.h" + +typedef struct dbg_handle dbg_handle; + +/** + * Debug operations. + */ +typedef struct debug_ops { + /** close the stabs handler. */ + void (*close)(dbg_handle *handle); + + /** start a new source object (compilation unit) */ + void (*so)(dbg_handle *handle, const char *filename); + + /** Main Program */ + void (*main_program)(dbg_handle *handle); + + /** dumps the stabs for a method begin */ + void (*method_begin)(dbg_handle *handle, ir_entity *ent, const be_stack_layout_t *layout); + + /** dumps the stabs for a method end */ + void (*method_end)(dbg_handle *handle); + + /** dump types */ + void (*types)(dbg_handle *handle); + + /** dump a variable in the global type */ + void (*variable)(dbg_handle *h, struct obstack *obst, ir_entity *ent); + + /** notify debug info about position change */ + void (*set_dbg_info)(dbg_handle *h, dbg_info *dbgi); +} debug_ops; + +/** The base class of all debug implementations. */ +struct dbg_handle { + const debug_ops *ops; +}; + +typedef dbg_handle* (*be_create_dbgout_module_func)(void); +void be_register_dbgout_module(const char *name, + be_create_dbgout_module_func func); + +#endif diff --git a/ir/be/be_t.h b/ir/be/be_t.h index 15d9323b2..d3c63fd5e 100644 --- a/ir/be/be_t.h +++ b/ir/be/be_t.h @@ -34,7 +34,6 @@ #include "be.h" #include "bearch.h" -#include "be_dbgout.h" #include "beirg.h" #define DUMP_NONE 0 @@ -68,9 +67,9 @@ struct be_options_t { int timing; /**< time the backend phases */ int opt_profile; /**< instrument code for profiling */ int omit_fp; /**< try to omit the frame pointer */ - int stabs_debug_support; /**< enable stabs debugging support */ int vrfy_option; /**< backend verify option */ int scheduler; /**< the scheduler */ + char target_os[128]; /**< target operating system name */ char ilp_server[128]; /**< the ilp server name */ char ilp_solver[128]; /**< the ilp solver name */ int statev; /**< enable stat event dumping */ @@ -83,7 +82,6 @@ struct be_main_env_t { be_options_t *options; arch_code_generator_t *cg; arch_irn_handler_t *phi_handler; - dbg_handle *db_handle; const char *cup_name; }; diff --git a/ir/be/bedbgout.c b/ir/be/bedbgout.c new file mode 100644 index 000000000..fd03dd12f --- /dev/null +++ b/ir/be/bedbgout.c @@ -0,0 +1,110 @@ +/* + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + +/** + * @file + * @brief Stabs support. + * @author Michael Beck + * @date 11.9.2006 + * @version $Id: bestabs.c 17143 2008-01-02 20:56:33Z beck $ + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "be_dbgout_t.h" +#include "bemodule.h" +#include "irtools.h" + +static dbg_handle *handle = NULL; + +void be_dbg_close(void) { + if (handle->ops->close) + handle->ops->close(handle); +} + +void be_dbg_so(const char *filename) { + if (handle->ops->so) + handle->ops->so(handle, filename); +} + +void be_dbg_main_program(void) { + if (handle->ops->main_program) + handle->ops->main_program(handle); +} + +void be_dbg_method_begin(ir_entity *ent, const be_stack_layout_t *layout) { + if (handle->ops->method_begin) + handle->ops->method_begin(handle, ent, layout); +} + +void be_dbg_method_end(void) { + if (handle->ops->method_end) + handle->ops->method_end(handle); +} + +void be_dbg_types(void) { + if (handle->ops->types) + handle->ops->types(handle); +} + +void be_dbg_variable(struct obstack *obst, ir_entity *ent) { + if (handle->ops->variable) + handle->ops->variable(handle, obst, ent); +} + +void be_dbg_set_dbg_info(dbg_info *dbgi) { + if (handle->ops->set_dbg_info) + handle->ops->set_dbg_info(handle, dbgi); +} + +static be_module_list_entry_t *dbgout_modules = NULL; +static be_create_dbgout_module_func selected_dbgout_module = NULL; + +void be_dbg_open(void) { + handle = selected_dbgout_module(); +} + +void be_register_dbgout_module(const char *name, + be_create_dbgout_module_func func); + +void be_register_dbgout_module(const char *name, + be_create_dbgout_module_func func) +{ + if (selected_dbgout_module == NULL) + selected_dbgout_module = func; + be_add_module_to_list(&dbgout_modules, name, func); +} + +static dbg_handle *create_null_dbgout_module(void) +{ + static const debug_ops null_ops; + static dbg_handle null_handle = { &null_ops }; + return &null_handle; +} + +void be_init_dbgout(void) { + lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be"); + + be_add_module_list_opt(be_grp, "debuginfo", "debug info format", + &dbgout_modules, (void**) &selected_dbgout_module); + be_register_dbgout_module("null", create_null_dbgout_module); +} + +BE_REGISTER_MODULE_CONSTRUCTOR(be_init_dbgout); diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c index 41cb56dc5..07260b6fe 100644 --- a/ir/be/begnuas.c +++ b/ir/be/begnuas.c @@ -50,7 +50,7 @@ typedef struct obstack obstack_t; /** by default, we generate assembler code for the Linux gas */ -be_gas_flavour_t be_gas_flavour = GAS_FLAVOUR_NORMAL; +be_gas_flavour_t be_gas_flavour = GAS_FLAVOUR_ELF; /** * Return the pseudo-instruction to be issued for a section switch @@ -61,8 +61,8 @@ be_gas_flavour_t be_gas_flavour = GAS_FLAVOUR_NORMAL; * @return the pseudo-instruction */ static const char *get_section_name(be_gas_section_t section) { - static const char *text[GAS_FLAVOUR_MAX][GAS_SECTION_MAX] = { - { + static const char *text[GAS_FLAVOUR_LAST+1][GAS_SECTION_LAST+1] = { + { /* GAS_FLAVOUR_ELF */ ".section\t.text", ".section\t.data", ".section\t.rodata", @@ -70,7 +70,7 @@ static const char *get_section_name(be_gas_section_t section) { ".section\t.tbss,\"awT\",@nobits", ".section\t.ctors,\"aw\",@progbits" }, - { + { /* GAS_FLAVOUR_MINGW */ ".section\t.text", ".section\t.data", ".section .rdata,\"dr\"", @@ -78,27 +78,29 @@ static const char *get_section_name(be_gas_section_t section) { ".section\t.tbss,\"awT\",@nobits", ".section\t.ctors,\"aw\",@progbits" }, - { + { /* GAS_FLAVOUR_YASM */ ".section\t.text", - ".section\t.data", - ".section\t.rodata", - ".section\t.bss", - ".section\t.tbss,\"awT\",@nobits", - ".section\t.ctors,\"aw\",@progbits" + ".section\t.data", + ".section\t.rodata", + ".section\t.bss", + ".section\t.tbss,\"awT\",@nobits", + ".section\t.ctors,\"aw\",@progbits" + }, + { /* GAS_FLAVOUR_MACH_O */ + ".text", + ".data", + ".const", + ".data", + "", /* TLS is not supported on Mach-O */ + "" /* constructors aren't marked with sections in Mach-O */ } }; - assert((int) be_gas_flavour >= 0 && be_gas_flavour < GAS_FLAVOUR_MAX); - assert((int) section >= 0 && section < GAS_SECTION_MAX); + assert((int) be_gas_flavour >= 0 && be_gas_flavour <= GAS_FLAVOUR_LAST); + assert((int) section >= 0 && section <= GAS_SECTION_LAST); return text[be_gas_flavour][section]; } -/** - * Emit necessary code to switch to a section. - * - * @param env the emitter environment - * @param section the section to switch to - */ void be_gas_emit_switch_section(be_gas_section_t section) { be_emit_char('\t'); be_emit_string(get_section_name(section)); @@ -106,6 +108,74 @@ void be_gas_emit_switch_section(be_gas_section_t section) { be_emit_write_line(); } +void be_gas_emit_function_prolog(ir_entity *entity, unsigned alignment) +{ + const char *name = get_entity_ld_name(entity); + + be_gas_emit_switch_section(GAS_SECTION_TEXT); + + /* write the begin line (used by scripts processing the assembler... */ + be_emit_write_line(); + be_emit_cstring("# -- Begin "); + be_emit_string(name); + be_emit_char('\n'); + be_emit_write_line(); + + if (be_gas_flavour != GAS_FLAVOUR_MACH_O) { + unsigned maximum_skip = (1 << alignment) - 1; + be_emit_cstring("\t.p2align "); + be_emit_irprintf("%u,,%u\n", alignment, maximum_skip); + be_emit_write_line(); + } + + if (get_entity_visibility(entity) == visibility_external_visible) { + be_emit_cstring(".global "); + be_emit_string(name); + be_emit_char('\n'); + be_emit_write_line(); + } + + switch (be_gas_flavour) { + case GAS_FLAVOUR_ELF: + be_emit_cstring("\t.type\t"); + be_emit_string(name); + be_emit_cstring(", @function\n"); + be_emit_write_line(); + break; + case GAS_FLAVOUR_MINGW: + be_emit_cstring("\t.def\t"); + be_emit_string(name); + be_emit_cstring(";\t.scl\t2;\t.type\t32;\t.endef\n"); + be_emit_write_line(); + break; + case GAS_FLAVOUR_MACH_O: + case GAS_FLAVOUR_YASM: + break; + } + be_emit_string(name); + be_emit_cstring(":\n"); + be_emit_write_line(); +} + +void be_gas_emit_function_epilog(ir_entity *entity) +{ + const char *name = get_entity_ld_name(entity); + + if (be_gas_flavour == GAS_FLAVOUR_ELF) { + be_emit_cstring("\t.size\t"); + be_emit_string(name); + be_emit_cstring(", .-"); + be_emit_string(name); + be_emit_char('\n'); + be_emit_write_line(); + } + + be_emit_cstring("# -- End "); + be_emit_string(name); + be_emit_char('\n'); + be_emit_write_line(); +} + /** * An environment containing all needed dumper data. * Currently we create the file completely in memory first, then @@ -385,7 +455,7 @@ static void dump_size_type(obstack_t *obst, size_t size) { break; default: - fprintf(stderr, "Try to dump a type with %d bytes\n", size); + fprintf(stderr, "Try to dump a type with %u bytes\n", (unsigned) size); assert(0); } } @@ -1003,12 +1073,14 @@ static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons obst = env->data_obst; if (is_Method_type(type)) { - if (get_method_img_section(ent) == section_constructors) { + if (be_gas_flavour != GAS_FLAVOUR_MACH_O + && get_method_img_section(ent) == section_constructors) { obst = env->ctor_obst; obstack_printf(obst, ".balign\t%u\n", align); dump_size_type(obst, align); obstack_printf(obst, "%s\n", ld_name); } + return; } @@ -1024,7 +1096,7 @@ static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons emit_as_common = 1; } - be_dbg_variable(env->main_env->db_handle, obst, ent); + be_dbg_variable(obst, ent); /* global or not global */ if (visibility == visibility_external_visible && !emit_as_common) { @@ -1046,7 +1118,8 @@ static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons if (variability == variability_uninitialized) { if (emit_as_common) { switch (be_gas_flavour) { - case GAS_FLAVOUR_NORMAL: + case GAS_FLAVOUR_ELF: + case GAS_FLAVOUR_MACH_O: case GAS_FLAVOUR_YASM: obstack_printf(obst, "\t.comm %s,%u,%u\n", ld_name, get_type_size_bytes(type), align); @@ -1055,8 +1128,6 @@ static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons obstack_printf(obst, "\t.comm %s,%u # %u\n", ld_name, get_type_size_bytes(type), align); break; - case GAS_FLAVOUR_MAX: - panic("invalid gas flavour selected"); } } else { obstack_printf(obst, "\t.zero %u\n", get_type_size_bytes(type)); diff --git a/ir/be/begnuas.h b/ir/be/begnuas.h index bffd756b6..a6d0a1756 100644 --- a/ir/be/begnuas.h +++ b/ir/be/begnuas.h @@ -34,23 +34,24 @@ * Sections. */ typedef enum section_t { - GAS_SECTION_TEXT = 0, /**< text section */ - GAS_SECTION_DATA = 1, /**< data section */ - GAS_SECTION_RODATA = 2, /**< rodata section */ - GAS_SECTION_COMMON = 3, /**< common section */ - GAS_SECTION_TLS = 4, /**< thread local storage section */ - GAS_SECTION_CTOR = 5, /**< ctor section for instrumentation code init */ - GAS_SECTION_MAX = 6 + GAS_SECTION_TEXT, /**< text section */ + GAS_SECTION_DATA, /**< data section */ + GAS_SECTION_RODATA, /**< rodata section */ + GAS_SECTION_COMMON, /**< common section */ + GAS_SECTION_TLS, /**< thread local storage section */ + GAS_SECTION_CTOR, /**< ctor section for instrumentation code init */ + GAS_SECTION_LAST = GAS_SECTION_CTOR } be_gas_section_t; /** * Support for some GAS "dialects". */ typedef enum asm_flavour_t { - GAS_FLAVOUR_NORMAL = 0, /**< normal gas (ELF) */ - GAS_FLAVOUR_MINGW = 1, /**< MinGW variant (no-ELF) */ - GAS_FLAVOUR_YASM = 2, /**< YASM GNU parser */ - GAS_FLAVOUR_MAX = 3 + GAS_FLAVOUR_ELF, /**< ELF variant */ + GAS_FLAVOUR_MINGW, /**< MinGW variant (no-ELF) */ + GAS_FLAVOUR_YASM, /**< YASM GNU parser */ + GAS_FLAVOUR_MACH_O, /**< Mach-O variant (as found on darwin, OS/X) */ + GAS_FLAVOUR_LAST = GAS_FLAVOUR_MACH_O } be_gas_flavour_t; /** The variable where the GAS dialect is stored. */ @@ -58,7 +59,6 @@ extern be_gas_flavour_t be_gas_flavour; /** * Generate all entities. - * @param env the emitter environment * @param main_env the main backend environment * @param emit_commons if non-zero, emit commons (non-local uninitialized entities) * @param only_emit_marked if non-zero, external allocated entities that do not have @@ -70,14 +70,20 @@ void be_gas_emit_decls(const be_main_env_t *main_env, /** * Switch the current output section to the given out. * - * @param env the emitter environment * @param section the new output section */ void be_gas_emit_switch_section(be_gas_section_t section); +/** + * emit assembler instructions necessary before starting function code + */ +void be_gas_emit_function_prolog(ir_entity *entity, unsigned alignment); + +void be_gas_emit_function_epilog(ir_entity *entity); + /** * Return the label prefix for labeled blocks. */ const char *be_gas_label_prefix(void); -#endif /* FIRM_BE_BEGNUAS_H */ +#endif diff --git a/ir/be/beirg_t.h b/ir/be/beirg_t.h index 3f3bc1ac4..61f0f28db 100644 --- a/ir/be/beirg_t.h +++ b/ir/be/beirg_t.h @@ -29,6 +29,7 @@ #include "beirg.h" #include "be_t.h" +#include "beabi.h" #include "irlivechk.h" /** diff --git a/ir/be/bemain.c b/ir/be/bemain.c index 27c8153a1..6a29f868a 100644 --- a/ir/be/bemain.c +++ b/ir/be/bemain.c @@ -87,9 +87,9 @@ static be_options_t be_options = { BE_TIME_OFF, /* no timing */ 0, /* no opt profile */ 0, /* try to omit frame pointer */ - 0, /* no stabs debugging output */ BE_VRFY_WARN, /* verification level: warn */ BE_SCHED_LIST, /* scheduler: list scheduler */ + "linux", /* target OS name */ "i44pc52.info.uni-karlsruhe.de", /* ilp server */ "cplex", /* ilp solver */ 0, /* enable statistic event dumping */ @@ -149,11 +149,11 @@ static const lc_opt_table_entry_t be_main_options[] = { LC_OPT_ENT_STR ("config", "read another config file containing backend options", config_file, sizeof(config_file)), LC_OPT_ENT_ENUM_MASK("dump", "dump irg on several occasions", &dump_var), LC_OPT_ENT_BOOL ("omitfp", "omit frame pointer", &be_options.omit_fp), - LC_OPT_ENT_BOOL ("stabs", "enable stabs debug support", &be_options.stabs_debug_support), LC_OPT_ENT_ENUM_PTR ("vrfy", "verify the backend irg", &vrfy_var), LC_OPT_ENT_BOOL ("time", "get backend timing statistics", &be_options.timing), LC_OPT_ENT_BOOL ("profile", "instrument the code for execution count profiling", &be_options.opt_profile), LC_OPT_ENT_ENUM_PTR ("sched", "select a scheduler", &sched_var), + LC_OPT_ENT_STR ("os", "specify target operating system", &be_options.target_os, sizeof(be_options.target_os)), #ifdef FIRM_STATISTICS LC_OPT_ENT_BOOL ("statev", "dump statistic events", &be_options.statev), LC_OPT_ENT_STR ("filtev", "filter for stat events (regex if support is active", &be_options.printev, sizeof(be_options.printev)), @@ -265,14 +265,14 @@ static be_main_env_t *be_init_env(be_main_env_t *env, FILE *file_handle) env->phi_handler = be_phi_handler_new(env->arch_env); arch_env_push_irn_handler(env->arch_env, env->phi_handler); - env->db_handle = be_options.stabs_debug_support ? be_stabs_open(file_handle) : be_nulldbg_open(); + be_dbg_open(); return env; } static void be_done_env(be_main_env_t *env) { env->arch_env->isa->impl->done(env->arch_env->isa); - be_dbg_close(env->db_handle); + be_dbg_close(); be_phi_handler_free(env->phi_handler); obstack_free(&env->obst, NULL); } @@ -409,8 +409,8 @@ static void be_main_loop(FILE *file_handle, const char *cup_name) isa = arch_env_get_isa(env.arch_env); - be_dbg_so(env.db_handle, cup_name); - be_dbg_types(env.db_handle); + be_dbg_so(cup_name); + be_dbg_types(); /* backend may provide an ordered list of irgs where code should be generated for */ irg_list = NEW_ARR_F(ir_graph *, 0); diff --git a/ir/be/bemodule.c b/ir/be/bemodule.c index 6c3d82923..3a9336b1d 100644 --- a/ir/be/bemodule.c +++ b/ir/be/bemodule.c @@ -47,6 +47,7 @@ void be_init_copyheur4(void); void be_init_copyheur5(void); void be_init_copystat(void); void be_init_daemelspill(void); +void be_init_dbgout(void); void be_init_arch_ia32(void); void be_init_arch_ppc32(void); void be_init_arch_mips(void); @@ -62,6 +63,7 @@ void be_init_spillbelady(void); void be_init_spillbelady2(void); void be_init_spillbelady3(void); void be_init_ssaconstr(void); +void be_init_stabs(void); void be_init_ifg(void); void be_init_irgmod(void); void be_init_loopana(void); @@ -91,6 +93,7 @@ void be_init_modules(void) be_init_blocksched(); be_init_spill(); be_init_spilloptions(); + be_init_dbgout(); be_init_listsched(); be_init_schedrss(); be_init_chordal_main(); @@ -109,6 +112,7 @@ void be_init_modules(void) be_init_ssaconstr(); be_init_state(); be_init_ifg(); + be_init_stabs(); be_init_arch_ia32(); be_init_arch_ppc32(); diff --git a/ir/be/bespilloptions.h b/ir/be/bespilloptions.h index 112fc6548..576a1b97d 100644 --- a/ir/be/bespilloptions.h +++ b/ir/be/bespilloptions.h @@ -40,4 +40,4 @@ void be_register_spiller(const char *name, be_spiller_t *spiller); void be_do_spill(be_irg_t *birg, const arch_register_class_t *cls); -#endif /* FIRM_BE_BESPILL_OPTIONS_H */ +#endif diff --git a/ir/be/bestabs.c b/ir/be/bestabs.c index a636a27e6..17140bedc 100644 --- a/ir/be/bestabs.c +++ b/ir/be/bestabs.c @@ -42,8 +42,11 @@ #include "irtools.h" #include "obst.h" #include "array.h" -#include "be_dbgout.h" +#include "be_dbgout_t.h" #include "beabi.h" +#include "bemodule.h" +#include "beemitter.h" +#include "dbginfo.h" /* Non-Stab Symbol and Stab Symbol Types */ enum stabs_types { @@ -114,13 +117,14 @@ enum stabs_types { */ typedef struct stabs_handle { dbg_handle base; /**< the base class */ - FILE *f; /**< the file write to */ ir_entity *cur_ent; /**< current method entity */ const be_stack_layout_t *layout; /**< current stack layout */ unsigned next_type_nr; /**< next type number */ pmap *type_map; /**< a map from type to type number */ const char *main_file; /**< name of the main source file */ const char *curr_file; /**< name of the current source file */ + unsigned label_num; + unsigned last_line; } stabs_handle; /** @@ -155,7 +159,9 @@ static void map_to_void(stabs_handle *h, ir_type *tp) { * generate the void type. */ static void gen_void_type(stabs_handle *h) { - fprintf(h->f, "\t.stabs\t\"void:t%u=%u\",%d,0,0,0\n", 0, 0, N_LSYM); + (void) h; + be_emit_irprintf("\t.stabs\t\"void:t%u=%u\",%d,0,0,0\n", 0, 0, N_LSYM); + be_emit_write_line(); } /* gen_void_type */ typedef struct walker_env { @@ -208,15 +214,16 @@ static void gen_primitive_type(stabs_handle *h, ir_type *tp) { type_num = get_type_number(h, tp); if (mode_is_int(mode)) { - char buf[64]; - fprintf(h->f, "\t.stabs\t\"%s:t%u=r%u;", get_type_name(tp), type_num, type_num); - tarval_snprintf(buf, sizeof(buf), get_mode_min(mode)); - fprintf(h->f, "%s;", buf); - tarval_snprintf(buf, sizeof(buf), get_mode_max(mode)); - fprintf(h->f, "%s;\",%d,0,0,0\n", buf, N_LSYM); + be_emit_irprintf("\t.stabs\t\"%s:t%u=r%u;", get_type_name(tp), type_num, type_num); + be_emit_tarval(get_mode_min(mode)); + be_emit_char(';'); + be_emit_tarval(get_mode_max(mode)); + be_emit_irprintf(";\",%d,0,0,0\n", N_LSYM); + be_emit_write_line(); } else if (mode_is_float(mode)) { int size = get_type_size_bytes(tp); - fprintf(h->f, "\t.stabs\t\"%s:t%u=r1;%d;0;\",%d,0,0,0\n", get_type_name(tp), type_num, size, N_LSYM); + be_emit_irprintf("\t.stabs\t\"%s:t%u=r1;%d;0;\",%d,0,0,0\n", get_type_name(tp), type_num, size, N_LSYM); + be_emit_write_line(); } } /* gen_primitive_type */ @@ -231,15 +238,16 @@ static void gen_enum_type(stabs_handle *h, ir_type *tp) { int i, n; SET_TYPE_READY(tp); - fprintf(h->f, "\t.stabs\t\"%s:T%u=e", get_type_name(tp), type_num); + be_emit_irprintf("\t.stabs\t\"%s:T%u=e", get_type_name(tp), type_num); for (i = 0, n = get_enumeration_n_enums(tp); i < n; ++i) { ir_enum_const *ec = get_enumeration_const(tp, i); char buf[64]; tarval_snprintf(buf, sizeof(buf), get_enumeration_value(ec)); - fprintf(h->f, "%s:%s,", get_enumeration_name(ec), buf); + be_emit_irprintf("%s:%s,", get_enumeration_name(ec), buf); } - fprintf(h->f, ";\",%d,0,0,0\n", N_LSYM); + be_emit_irprintf(";\",%d,0,0,0\n", N_LSYM); + be_emit_write_line(); } /* gen_enum_type */ /** @@ -250,7 +258,7 @@ void print_pointer_type(stabs_handle *h, ir_type *tp, int local) { ir_type *el_tp = get_pointer_points_to_type(tp); unsigned el_num = get_type_number(h, el_tp); - fprintf(h->f, "%u=*%u", type_num, el_num); + be_emit_irprintf("%u=*%u", type_num, el_num); } /** @@ -267,9 +275,10 @@ static void gen_pointer_type(wenv_t *env, ir_type *tp) { if (! IS_TYPE_READY(el_tp)) waitq_put(env->wq, el_tp); - fprintf(h->f, "\t.stabs\t\"%s:t", get_type_name(tp)); + be_emit_irprintf("\t.stabs\t\"%s:t", get_type_name(tp)); print_pointer_type(h, tp, 0); - fprintf(h->f, "\",%d,0,0,0\n", N_LSYM); + be_emit_irprintf("\",%d,0,0,0\n", N_LSYM); + be_emit_write_line(); } /* gen_pointer_type */ /** @@ -281,7 +290,7 @@ static void print_array_type(stabs_handle *h, ir_type *tp, int local) { unsigned type_num = local ? h->next_type_nr++ : get_type_number(h, tp); int *perm; - fprintf(h->f, "%u=a", type_num); + be_emit_irprintf("%u=a", type_num); NEW_ARR_A(int, perm, n); for (i = 0; i < n; ++i) { perm[i] = get_array_order(tp, i); @@ -295,12 +304,12 @@ static void print_array_type(stabs_handle *h, ir_type *tp, int local) { long max = get_array_upper_bound_int(tp, dim); /* FIXME r1 must be integer type, but seems to work for now */ - fprintf(h->f, "r1;%ld;%ld;", min, max-1); + be_emit_irprintf("r1;%ld;%ld;", min, max-1); } } type_num = get_type_number(h, etp); - fprintf(h->f, "%d", type_num); + be_emit_irprintf("%d", type_num); } /** @@ -317,11 +326,12 @@ static void gen_array_type(wenv_t *env, ir_type *tp) { if (! IS_TYPE_READY(etp)) waitq_put(env->wq, etp); - fprintf(h->f, "\t.stabs\t\"%s:t", get_type_name(tp)); + be_emit_irprintf("\t.stabs\t\"%s:t", get_type_name(tp)); print_array_type(h, tp, 0); - fprintf(h->f, "\",%d,0,0,0\n", N_LSYM); + be_emit_irprintf("\",%d,0,0,0\n", N_LSYM); + be_emit_write_line(); } /* gen_array_type */ /** @@ -347,7 +357,7 @@ static void gen_struct_union_type(wenv_t *env, ir_type *tp) { else if (is_Union_type(tp)) desc = 'u'; - fprintf(h->f, "\t.stabs\t\"%s:Tt%u=%c%d", + be_emit_irprintf("\t.stabs\t\"%s:Tt%u=%c%d", get_type_name(tp), type_num, desc, get_type_size_bytes(tp)); for (i = 0, n = get_compound_n_members(tp); i < n; ++i) { @@ -373,11 +383,11 @@ static void gen_struct_union_type(wenv_t *env, ir_type *tp) { bofs = (ofs + get_entity_offset(ent)) * 8 + get_entity_offset_bits_remainder(ent); /* name:type, bit offset from the start of the struct', number of bits in the element. */ - fprintf(h->f, "%s:%u,%d,%u;", get_entity_name(ent), type_num, bofs, size); + be_emit_irprintf("%s:%u,%d,%u;", get_entity_name(ent), type_num, bofs, size); } } else { /* no bitfield */ - fprintf(h->f, "%s:", get_entity_name(ent)); + be_emit_irprintf("%s:", get_entity_name(ent)); if (is_Array_type(mtp)) { /* use a local array definition */ @@ -389,13 +399,14 @@ static void gen_struct_union_type(wenv_t *env, ir_type *tp) { type_num = get_type_number(h, mtp); /* name:type, bit offset from the start of the struct', number of bits in the element. */ - fprintf(h->f, "%u", type_num); + be_emit_irprintf("%u", type_num); } size = get_type_size_bytes(mtp) * 8; - fprintf(h->f, ",%d,%u;", ofs * 8, size); + be_emit_irprintf(",%d,%u;", ofs * 8, size); } } - fprintf(h->f, ";\",%d,0,0,0\n", N_LSYM); + be_emit_irprintf(";\",%d,0,0,0\n", N_LSYM); + be_emit_write_line(); } /* gen_struct_type */ /** @@ -419,7 +430,7 @@ static void gen_method_type(wenv_t *env, ir_type *tp) { } res_type_num = get_type_number(h, rtp); - fprintf(h->f, "\t.stabs\t\"%s:t%u=f%u", get_type_name(tp), type_num, res_type_num); + be_emit_irprintf("\t.stabs\t\"%s:t%u=f%u", get_type_name(tp), type_num, res_type_num); /* handle more than one return type */ for (i = 1; i < n; ++i) { @@ -427,9 +438,10 @@ static void gen_method_type(wenv_t *env, ir_type *tp) { if (! IS_TYPE_READY(rtp)) waitq_put(env->wq, rtp); res_type_num = get_type_number(h, rtp); - fprintf(h->f, ",%u", res_type_num); + be_emit_irprintf(",%u", res_type_num); } - fprintf(h->f, "\",%d,0,0,0\n", N_LSYM); + be_emit_irprintf("\",%d,0,0,0\n", N_LSYM); + be_emit_write_line(); } /* gen_method_type */ /** @@ -558,46 +570,59 @@ static void gen_types(stabs_handle *h) { static void stabs_so(dbg_handle *handle, const char *filename) { stabs_handle *h = (stabs_handle *)handle; h->main_file = h->curr_file = filename; - fprintf(h->f, "\t.stabs\t\"%s\",%d,0,0,.Ltext0\n", filename, N_SO); + be_emit_irprintf("\t.stabs\t\"%s\",%d,0,0,.Ltext0\n", filename, N_SO); + be_emit_write_line(); } /* stabs_so */ -/** - * end an include file - */ -static void stabs_include_end(dbg_handle *handle) { - stabs_handle *h = (stabs_handle *)handle; - h->curr_file = h->main_file; -} /* stabs_include_end */ - -/** - * start an include file - */ -static void stabs_include_begin(dbg_handle *handle, const char *filename) { - stabs_handle *h = (stabs_handle *)handle; - if (h->main_file != h->curr_file) - stabs_include_end(handle); - h->curr_file = filename; - fprintf(h->f, "\t.stabs\t\"%s\",%d,0,0,0\n", filename, N_SOL); -} /* stabs_include_begin */ - /** * Main Program */ static void stabs_main_program(dbg_handle *handle) { - stabs_handle *h = (stabs_handle *)handle; + (void) handle; ir_graph *irg = get_irp_main_irg(); if (irg) { - fprintf(h->f, "\t.stabs\t\"%s\",%d,0,0,0\n", get_entity_name(get_irg_entity(irg)), N_MAIN); + be_emit_irprintf("\t.stabs\t\"%s\",%d,0,0,0\n", get_entity_name(get_irg_entity(irg)), N_MAIN); + be_emit_write_line(); } } /* stabs_main_program */ -/** - * prints a line number - */ -static void stabs_line(dbg_handle *handle, unsigned lineno, const char *address) { - stabs_handle *h = (stabs_handle *)handle; - fprintf(h->f, "\t.stabn\t%d, 0, %u, %s-%s\n", N_SLINE, lineno, address, get_entity_ld_name(h->cur_ent)); -} /* stabs_line */ +static void stabs_set_dbg_info(dbg_handle *h, dbg_info *dbgi) +{ + stabs_handle *handle = (stabs_handle*) h; + unsigned lineno; + const char *fname = ir_retrieve_dbg_info(dbgi, &lineno); + + if (fname == NULL) + return; + + if (handle->curr_file != fname) { + /* TODO: escape filename correctly */ + if (handle->curr_file != handle->main_file) { + be_emit_irprintf("\t.stabs\t\"%s\",%d,0,0,0\n", handle->curr_file, + N_EINCL); + be_emit_write_line(); + } + if (fname != handle->main_file) { + be_emit_irprintf("\t.stabs\t\"%s\",%d,0,0,0\n", fname, N_SOL); + be_emit_write_line(); + } + handle->curr_file = fname; + } + if (handle->last_line != lineno) { + char label[64]; + + snprintf(label, sizeof(label), ".LM%u", ++handle->label_num); + handle->last_line = lineno; + + be_emit_irprintf("\t.stabn\t%d, 0, %u, %s-%s\n", N_SLINE, lineno, + label, get_entity_ld_name(handle->cur_ent)); + be_emit_write_line(); + + be_emit_string(label); + be_emit_cstring(":\n"); + be_emit_write_line(); + } +} /** * dump the stabs for a method begin @@ -620,12 +645,13 @@ static void stabs_method_begin(dbg_handle *handle, ir_entity *ent, const be_stac else rtp = NULL; type_num = get_type_number(h, rtp); - fprintf(h->f, "\t.stabs\t\"%s:%c%u\",%u,0,0,%s\n", + be_emit_irprintf("\t.stabs\t\"%s:%c%u\",%u,0,0,%s\n", get_entity_name(ent), get_entity_visibility(ent) == visibility_external_visible ? 'F' : 'f', type_num, N_FUN, get_entity_ld_name(ent)); + be_emit_write_line(); /* create parameter entries */ between_size = get_type_size_bytes(layout->between_type); @@ -647,7 +673,7 @@ static void stabs_method_begin(dbg_handle *handle, ir_entity *ent, const be_stac if (stack_ent) { ofs = get_entity_offset(stack_ent) + between_size; } - fprintf(h->f, "\t.stabs\t\"%s:p", name); + be_emit_irprintf("\t.stabs\t\"%s:p", name); if (is_Array_type(ptp)) { /* use a local array definition */ print_array_type(h, ptp, 1); @@ -658,10 +684,11 @@ static void stabs_method_begin(dbg_handle *handle, ir_entity *ent, const be_stac type_num = get_type_number(h, ptp); /* name:type, bit offset from the start of the struct', number of bits in the element. */ - fprintf(h->f, "%u", type_num); + be_emit_irprintf("%u", type_num); } - fprintf(h->f, "\",%d,0,0,%d\n", N_PSYM, ofs); + be_emit_irprintf("\",%d,0,0,%d\n", N_PSYM, ofs); + be_emit_write_line(); } } /* stabs_method_begin */ @@ -695,13 +722,17 @@ static void stabs_method_end(dbg_handle *handle) { type_num = get_type_number(h, tp); ofs = -frame_size + get_entity_offset(ent); - fprintf(h->f, "\t.stabs\t\"%s:%u\",%d,0,0,%d\n", + be_emit_irprintf("\t.stabs\t\"%s:%u\",%d,0,0,%d\n", get_entity_name(ent), type_num, N_LSYM, ofs); + be_emit_write_line(); } /* we need a lexical block here */ - fprintf(h->f, "\t.stabn\t%d,0,0,%s-%s\n", N_LBRAC, ld_name, ld_name); - fprintf(h->f, "\t.stabn\t%d,0,0,.Lscope%u-%s\n", N_RBRAC, scope_nr, ld_name); - fprintf(h->f, ".Lscope%u:\n", scope_nr); + be_emit_irprintf("\t.stabn\t%d,0,0,%s-%s\n", N_LBRAC, ld_name, ld_name); + be_emit_write_line(); + be_emit_irprintf("\t.stabn\t%d,0,0,.Lscope%u-%s\n", N_RBRAC, scope_nr, ld_name); + be_emit_write_line(); + be_emit_irprintf(".Lscope%u:\n", scope_nr); + be_emit_write_line(); ++scope_nr; h->cur_ent = NULL; @@ -748,7 +779,7 @@ static void stabs_variable(dbg_handle *handle, struct obstack *obst, ir_entity * if (obst) obstack_printf(obst, "%s", buf); else - fprintf(h->f, "%s", buf); + be_emit_irprintf("%s", buf); } /* stabs_variable */ /** @@ -764,27 +795,19 @@ static void stabs_close(dbg_handle *handle) { static const debug_ops stabs_ops = { stabs_close, stabs_so, - stabs_include_begin, - stabs_include_end, stabs_main_program, stabs_method_begin, stabs_method_end, - stabs_line, stabs_types, - stabs_variable + stabs_variable, + stabs_set_dbg_info }; -/* Opens the NULL handler */ -dbg_handle *be_nulldbg_open(void) { - return NULL; -} /* be_nulldbg_open */ - /* Opens a stabs handler */ -dbg_handle *be_stabs_open(FILE *out) { +dbg_handle *be_stabs_open(void) { stabs_handle *h = xmalloc(sizeof(*h)); h->base.ops = &stabs_ops; - h->f = out; h->cur_ent = NULL; h->layout = NULL; h->next_type_nr = 0; @@ -793,72 +816,11 @@ dbg_handle *be_stabs_open(FILE *out) { h->curr_file = NULL; return &h->base; -} /* stabs_open */ - -/** close a debug handler. */ -void be_dbg_close(dbg_handle *h) { - if (h && h->ops->close) - h->ops->close(h); -} /* be_dbg_close */ - -/** - * start a new source object (compilation unit) - */ -void be_dbg_so(dbg_handle *h, const char *filename) { - if (h && h->ops->so) - h->ops->so(h, filename); -} /* be_dbg_begin */ - -/** - * start an include file - */ -void be_dbg_include_begin(dbg_handle *h, const char *filename) { - if (h && h->ops->include_begin) - h->ops->include_begin(h, filename); -} /* stabs_include_begin */ +} -/** - * end an include file - */ -void be_dbg_include_end(dbg_handle *h) { - if (h && h->ops->include_end) - h->ops->include_end(h); -} /* stabs_include_end */ +void be_init_stabs(void) +{ + be_register_dbgout_module("stabs", be_stabs_open); +} -/** - * Main program - */ -void be_dbg_main_program(dbg_handle *h) { - if (h && h->ops->main_program) - h->ops->main_program(h); -} /* be_dbg_main_program */ - -/** debug for a method begin */ -void be_dbg_method_begin(dbg_handle *h, ir_entity *ent, const be_stack_layout_t *layout) { - if (h && h->ops->method_begin) - h->ops->method_begin(h, ent, layout); -} /* be_dbg_method_begin */ - -/** debug for a method end */ -void be_dbg_method_end(dbg_handle *h) { - if (h && h->ops->method_end) - h->ops->method_end(h); -} /* be_dbg_method_end */ - -/** debug for line number */ -void be_dbg_line(dbg_handle *h, unsigned lineno, const char *address) { - if (h && h->ops->line) - h->ops->line(h, lineno, address); -} /* be_dbg_line */ - -/** dump types */ -void be_dbg_types(dbg_handle *h) { - if (h && h->ops->types) - h->ops->types(h); -} /* be_dbg_types */ - -/** dump a global */ -void be_dbg_variable(dbg_handle *h, struct obstack *obst, ir_entity *ent) { - if (h && h->ops->variable) - h->ops->variable(h, obst, ent); -} /* be_dbg_variable */ +BE_REGISTER_MODULE_CONSTRUCTOR(be_init_stabs); diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index c1ae0589a..6c65bf501 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -2083,9 +2083,10 @@ static const backend_params *ia32_get_libfirm_params(void) { } static const lc_opt_enum_int_items_t gas_items[] = { - { "normal", GAS_FLAVOUR_NORMAL }, + { "elf", GAS_FLAVOUR_ELF }, { "mingw", GAS_FLAVOUR_MINGW }, { "yasm", GAS_FLAVOUR_YASM }, + { "macho", GAS_FLAVOUR_MACH_O }, { NULL, 0 } }; diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 16021df74..4f3c794cc 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -51,6 +51,7 @@ #include "../beemitter.h" #include "../begnuas.h" #include "../beirg_t.h" +#include "../be_dbgout.h" #include "ia32_emitter.h" #include "gen_ia32_emitter.h" @@ -334,48 +335,6 @@ void ia32_emit_extend_suffix(const ir_mode *mode) } } -static void ia32_emit_function_object(const char *name) -{ - switch (be_gas_flavour) { - case GAS_FLAVOUR_NORMAL: - be_emit_cstring("\t.type\t"); - be_emit_string(name); - be_emit_cstring(", @function\n"); - be_emit_write_line(); - break; - case GAS_FLAVOUR_MINGW: - be_emit_cstring("\t.def\t"); - be_emit_string(name); - be_emit_cstring(";\t.scl\t2;\t.type\t32;\t.endef\n"); - be_emit_write_line(); - break; - case GAS_FLAVOUR_YASM: - break; - default: - break; - } -} - -static void ia32_emit_function_size(const char *name) -{ - switch (be_gas_flavour) { - case GAS_FLAVOUR_NORMAL: - be_emit_cstring("\t.size\t"); - be_emit_string(name); - be_emit_cstring(", .-"); - be_emit_string(name); - be_emit_char('\n'); - be_emit_write_line(); - break; - case GAS_FLAVOUR_MINGW: - case GAS_FLAVOUR_YASM: - break; - default: - break; - } -} - - void ia32_emit_source_register_or_immediate(const ir_node *node, int pos) { ir_node *in = get_irn_n(node, pos); @@ -1919,41 +1878,6 @@ static void ia32_register_emitters(void) { #undef IA32_EMIT } -static const char *last_name = NULL; -static unsigned last_line = -1; -static unsigned num = -1; - -/** - * Emit the debug support for node node. - */ -static void ia32_emit_dbg(const ir_node *node) -{ - dbg_info *db = get_irn_dbg_info(node); - unsigned lineno; - const char *fname = ir_retrieve_dbg_info(db, &lineno); - - if (! cg->birg->main_env->options->stabs_debug_support) - return; - - if (fname) { - if (last_name != fname) { - last_line = -1; - be_dbg_include_begin(cg->birg->main_env->db_handle, fname); - last_name = fname; - } - if (last_line != lineno) { - char name[64]; - - snprintf(name, sizeof(name), ".LM%u", ++num); - last_line = lineno; - be_dbg_line(cg->birg->main_env->db_handle, lineno, name); - be_emit_string(name); - be_emit_cstring(":\n"); - be_emit_write_line(); - } - } -} - typedef void (*emit_func_ptr) (const ir_node *); /** @@ -1967,7 +1891,9 @@ static void ia32_emit_node(const ir_node *node) if (op->ops.generic) { emit_func_ptr func = (emit_func_ptr) op->ops.generic; - ia32_emit_dbg(node); + + be_dbg_set_dbg_info(get_irn_dbg_info(node)); + (*func) (node); } else { emit_Nothing(node); @@ -1986,17 +1912,6 @@ static void ia32_emit_alignment(unsigned align, unsigned skip) be_emit_write_line(); } -/** - * Emits gas alignment directives for Functions depended on cpu architecture. - */ -static void ia32_emit_align_func(void) -{ - unsigned align = ia32_cg_config.function_alignment; - unsigned maximum_skip = (1 << align) - 1; - - ia32_emit_alignment(align, maximum_skip); -} - /** * Emits gas alignment directives for Labels depended on cpu architecture. */ @@ -2129,63 +2044,12 @@ static void ia32_gen_block(ir_node *block, ir_node *last_block) ia32_emit_block_header(block, last_block); /* emit the contents of the block */ - ia32_emit_dbg(block); + be_dbg_set_dbg_info(get_irn_dbg_info(block)); sched_foreach(block, node) { ia32_emit_node(node); } } -/** - * Emits code for function start. - */ -static void ia32_emit_func_prolog(ir_graph *irg) -{ - ir_entity *irg_ent = get_irg_entity(irg); - const char *irg_name = get_entity_ld_name(irg_ent); - const be_irg_t *birg = cg->birg; - - /* write the begin line (used by scripts processing the assembler... */ - be_emit_write_line(); - be_emit_cstring("# -- Begin "); - be_emit_string(irg_name); - be_emit_char('\n'); - be_emit_write_line(); - - be_gas_emit_switch_section(GAS_SECTION_TEXT); - be_dbg_method_begin(birg->main_env->db_handle, irg_ent, be_abi_get_stack_layout(birg->abi)); - ia32_emit_align_func(); - if (get_entity_visibility(irg_ent) == visibility_external_visible) { - be_emit_cstring(".global "); - be_emit_string(irg_name); - be_emit_char('\n'); - be_emit_write_line(); - } - ia32_emit_function_object(irg_name); - be_emit_string(irg_name); - be_emit_cstring(":\n"); - be_emit_write_line(); -} - -/** - * Emits code for function end - */ -static void ia32_emit_func_epilog(ir_graph *irg) -{ - const char *irg_name = get_entity_ld_name(get_irg_entity(irg)); - const be_irg_t *birg = cg->birg; - - ia32_emit_function_size(irg_name); - be_dbg_method_end(birg->main_env->db_handle); - - be_emit_cstring("# -- End "); - be_emit_string(irg_name); - be_emit_char('\n'); - be_emit_write_line(); - - be_emit_char('\n'); - be_emit_write_line(); -} - /** * Block-walker: * Sets labels for control flow nodes (jump target) @@ -2218,8 +2082,9 @@ void ia32_emit_exc_label(const ir_node *node) */ void ia32_gen_routine(ia32_code_gen_t *ia32_cg, ir_graph *irg) { - ir_node *block; - ir_node *last_block = NULL; + ir_node *block; + ir_node *last_block = NULL; + ir_entity *entity = get_irg_entity(irg); int i, n; cg = ia32_cg; @@ -2228,7 +2093,9 @@ void ia32_gen_routine(ia32_code_gen_t *ia32_cg, ir_graph *irg) ia32_register_emitters(); - ia32_emit_func_prolog(irg); + be_dbg_method_begin(entity, be_abi_get_stack_layout(cg->birg->abi)); + be_gas_emit_function_prolog(entity, ia32_cg_config.function_alignment); + irg_block_walk_graph(irg, ia32_gen_labels, NULL, NULL); n = ARR_LEN(cg->blk_sched); @@ -2245,7 +2112,10 @@ void ia32_gen_routine(ia32_code_gen_t *ia32_cg, ir_graph *irg) last_block = block; } - ia32_emit_func_epilog(irg); + be_gas_emit_function_epilog(entity); + be_dbg_method_end(); + be_emit_char('\n'); + be_emit_write_line(); } void ia32_init_emitter(void)