/* * This file is part of libFirm. * Copyright (C) 2016 University of Karlsruhe. */ /** * @file * @brief Helper functions for emitting assembly from a firm graph. * @author Matthias Braun */ #include "beemithlp.h" #include "be_t.h" #include "bearch.h" #include "bedwarf.h" #include "beemitter.h" #include "begnuas.h" #include "benode.h" #include "dbginfo.h" #include "debug.h" #include "firm_types.h" #include "iredges.h" #include "irnode_t.h" #include "irop_t.h" #include "util.h" static void be_emit_unknown(ir_node const *const node) { if (be_options.verbose_asm) { arch_register_t const *const reg = arch_get_irn_register_out(node, 0); be_emit_irprintf("\t/* unknown in %s */", reg->name); be_emit_finish_line_gas(node); } } void be_init_emitters(void) { ir_clear_opcodes_generic_func(); be_set_emitter(op_Phi, be_emit_nothing); be_set_emitter(op_be_Keep, be_emit_nothing); be_set_emitter(op_be_Start, be_emit_nothing); be_set_emitter(op_be_Unknown, be_emit_unknown); } void be_emit_nothing(ir_node const *const node) { (void)node; } void be_emit_node(ir_node const *const node) { be_dwarf_location(get_irn_dbg_info(node)); ir_op *const op = get_irn_op(node); emit_func *const emit = get_generic_function_ptr(emit_func, op); DEBUG_ONLY(if (!emit) panic("no emit handler for node %+F (%+G, graph %+F)", node, node, get_irn_irg(node));) emit(node); } void be_emit_pad_comment(void) { size_t col = be_emit_get_column(); col = MIN(col, 30); /* 34 spaces */ be_emit_string_len(" ", 34 - col); } void be_emit_init_cf_links(ir_node **const block_schedule) { ir_node *prev = NULL; for (size_t i = 0, n = ARR_LEN(block_schedule); i < n; ++i) { ir_node *const block = block_schedule[i]; /* Initialize cfop link */ for (unsigned n = get_Block_n_cfgpreds(block); n-- > 0; ) { ir_node *pred = get_Block_cfgpred(block, n); set_irn_link(pred, block); } /* initialize pred block links */ set_irn_link(block, prev); prev = block; } } be_cond_branch_projs_t be_get_cond_branch_projs(ir_node const *const node) { be_cond_branch_projs_t projs = { NULL, NULL }; foreach_out_edge(node, edge) { ir_node *const proj = get_edge_src_irn(edge); unsigned const pn = get_Proj_num(proj); switch (pn) { case pn_Cond_false: projs.f = proj; continue; case pn_Cond_true: projs.t = proj; continue; } panic("invalid Proj for branch"); } assert(projs.f && projs.t); return projs; } void be_emit_cfop_target(ir_node const *const jmp) { ir_node *const target = be_emit_get_cfop_target(jmp); be_gas_emit_block_name(target); } void be_emit_cfop_target_pos(ir_node const *const jmp, unsigned const pos) { ir_node *const proj = get_Proj_for_pn(jmp, pos); be_emit_cfop_target(proj); } bool be_is_fallthrough(ir_node const *const jmp) { ir_node *const block = get_nodes_block(jmp); ir_node *const target = be_emit_get_cfop_target(jmp); return be_emit_get_prev_block(target) == block; }