Commit e3943c4c authored by Robin Redeker's avatar Robin Redeker
Browse files

added amd64 backend code (which doesn't do much yet).

[r27454]
parent 737ff982
/*
* 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 emit assembler for a backend graph
* @version $Id: amd64_emitter.c 26746 2009-11-27 08:53:15Z matze $
*/
#include "config.h"
#include <limits.h>
#include "xmalloc.h"
#include "tv.h"
#include "iredges.h"
#include "debug.h"
#include "irgwalk.h"
#include "irprintf.h"
#include "irop_t.h"
#include "irargs_t.h"
#include "irprog.h"
#include "../besched.h"
#include "amd64_emitter.h"
#include "gen_amd64_emitter.h"
#include "amd64_nodes_attr.h"
#include "amd64_new_nodes.h"
#define SNPRINTF_BUF_LEN 128
/**
* Returns the register at in position pos.
*/
static const arch_register_t *get_in_reg(const ir_node *node, int pos)
{
ir_node *op;
const arch_register_t *reg = NULL;
assert(get_irn_arity(node) > pos && "Invalid IN position");
/* The out register of the operator at position pos is the
in register we need. */
op = get_irn_n(node, pos);
reg = arch_get_irn_register(op);
assert(reg && "no in register found");
return reg;
}
/**
* Returns the register at out position pos.
*/
static const arch_register_t *get_out_reg(const ir_node *node, int pos)
{
ir_node *proj;
const arch_register_t *reg = NULL;
/* 1st case: irn is not of mode_T, so it has only */
/* one OUT register -> good */
/* 2nd case: irn is of mode_T -> collect all Projs and ask the */
/* Proj with the corresponding projnum for the register */
if (get_irn_mode(node) != mode_T) {
reg = arch_get_irn_register(node);
} else if (is_amd64_irn(node)) {
reg = arch_irn_get_register(node, pos);
} else {
const ir_edge_t *edge;
foreach_out_edge(node, edge) {
proj = get_edge_src_irn(edge);
assert(is_Proj(proj) && "non-Proj from mode_T node");
if (get_Proj_proj(proj) == pos) {
reg = arch_get_irn_register(proj);
break;
}
}
}
assert(reg && "no out register found");
return reg;
}
/*************************************************************
* _ _ __ _ _
* (_) | | / _| | | | |
* _ __ _ __ _ _ __ | |_| |_ | |__ ___| |_ __ ___ _ __
* | '_ \| '__| | '_ \| __| _| | '_ \ / _ \ | '_ \ / _ \ '__|
* | |_) | | | | | | | |_| | | | | | __/ | |_) | __/ |
* | .__/|_| |_|_| |_|\__|_| |_| |_|\___|_| .__/ \___|_|
* | | | |
* |_| |_|
*************************************************************/
void amd64_emit_immediate(const ir_node *node)
{
(void) node;
/* TODO */
}
void amd64_emit_source_register(const ir_node *node, int pos)
{
const arch_register_t *reg = get_in_reg(node, pos);
be_emit_string(arch_register_get_name(reg));
}
void amd64_emit_dest_register(const ir_node *node, int pos)
{
const arch_register_t *reg = get_out_reg(node, pos);
be_emit_string(arch_register_get_name(reg));
}
/**
* Returns the target label for a control flow node.
*/
static void amd64_emit_cfop_target(const ir_node *node)
{
ir_node *block = get_irn_link(node);
be_emit_irprintf("BLOCK_%ld", get_irn_node_nr(block));
}
/***********************************************************************************
* _ __ _
* (_) / _| | |
* _ __ ___ __ _ _ _ __ | |_ _ __ __ _ _ __ ___ _____ _____ _ __| | __
* | '_ ` _ \ / _` | | '_ \ | _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
* | | | | | | (_| | | | | | | | | | | (_| | | | | | | __/\ V V / (_) | | | <
* |_| |_| |_|\__,_|_|_| |_| |_| |_| \__,_|_| |_| |_|\___| \_/\_/ \___/|_| |_|\_\
*
***********************************************************************************/
/**
* Emits code for a unconditional jump.
*/
static void emit_Jmp(const ir_node *node)
{
ir_node *block;
/* for now, the code works for scheduled and non-schedules blocks */
block = get_nodes_block(node);
be_emit_cstring("\tjmp ");
amd64_emit_cfop_target(node);
be_emit_finish_line_gas(node);
}
/**
* Enters the emitter functions for handled nodes into the generic
* pointer of an opcode.
*/
static void amd64_register_emitters(void)
{
/* some convienience macros to register additional emitter functions
(other than the generated ones) */
#define amd64_EMIT(a) op_amd64_##a->ops.generic = (op_func)emit_amd64_##a
#define EMIT(a) op_##a->ops.generic = (op_func)emit_##a
#define BE_EMIT(a) op_be_##a->ops.generic = (op_func)emit_be_##a
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
/* register all emitter functions defined in spec */
amd64_register_spec_emitters();
/* register addtional emitter functions if needed */
EMIT(Jmp);
#undef amd64_EMIT
#undef BE_EMIT
#undef EMIT
}
typedef void (*emit_func_ptr) (const ir_node *);
/**
* Emits code for a node.
*/
static void amd64_emit_node(const ir_node *node)
{
ir_op *op = get_irn_op(node);
if (op->ops.generic) {
emit_func_ptr func = (emit_func_ptr) op->ops.generic;
(*func) (node);
} else {
ir_fprintf(stderr, "No emitter for node %+F\n", node);
}
}
/**
* Walks over the nodes in a block connected by scheduling edges
* and emits code for each node.
*/
static void amd64_gen_block(ir_node *block, void *data)
{
ir_node *node;
(void) data;
if (! is_Block(block))
return;
be_emit_cstring("BLOCK_");
be_emit_irprintf("%ld:\n", get_irn_node_nr(block));
be_emit_write_line();
sched_foreach(block, node) {
amd64_emit_node(node);
}
}
/**
* Emits code for function start.
*/
static void amd64_emit_func_prolog(ir_graph *irg)
{
const char *irg_name = get_entity_name(get_irg_entity(irg));
/* TODO: emit function header */
be_emit_cstring("/* start of ");
be_emit_string(irg_name);
be_emit_cstring(" */\n");
be_emit_write_line();
}
/**
* Emits code for function end
*/
static void amd64_emit_func_epilog(ir_graph *irg)
{
const char *irg_name = get_entity_name(get_irg_entity(irg));
/* TODO: emit function end */
be_emit_cstring("/* end of ");
be_emit_string(irg_name);
be_emit_cstring(" */\n");
be_emit_write_line();
}
/**
* Sets labels for control flow nodes (jump target)
* TODO: Jump optimization
*/
static void amd64_gen_labels(ir_node *block, void *env)
{
ir_node *pred;
int n = get_Block_n_cfgpreds(block);
(void) env;
for (n--; n >= 0; n--) {
pred = get_Block_cfgpred(block, n);
set_irn_link(pred, block);
}
}
/**
* Main driver
*/
void amd64_gen_routine(const amd64_code_gen_t *cg, ir_graph *irg)
{
(void)cg;
/* register all emitter functions */
amd64_register_emitters();
amd64_emit_func_prolog(irg);
irg_block_walk_graph(irg, amd64_gen_labels, NULL, NULL);
irg_walk_blkwise_graph(irg, NULL, amd64_gen_block, NULL);
amd64_emit_func_epilog(irg);
}
/*
* 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 declarations for emit functions
* @version $Id: amd64_emitter.h 26317 2009-08-05 10:53:46Z matze $
*/
#ifndef FIRM_BE_amd64_amd64_EMITTER_H
#define FIRM_BE_amd64_amd64_EMITTER_H
#include "irargs_t.h"
#include "irnode.h"
#include "debug.h"
#include "../bearch.h"
#include "../beemitter.h"
#include "bearch_amd64_t.h"
void amd64_emit_source_register(const ir_node *node, int pos);
void amd64_emit_dest_register(const ir_node *node, int pos);
void amd64_emit_immediate(const ir_node *node);
int get_amd64_reg_nr(ir_node *irn, int posi, int in_out);
const char *get_amd64_in_reg_name(ir_node *irn, int pos);
void amd64_gen_routine(const amd64_code_gen_t *cg, ir_graph *irg);
#endif
/*
* 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 This file implements the creation of the achitecture specific firm
* opcodes and the coresponding node constructors for the amd64
* assembler irg.
* @version $Id: amd64_new_nodes.c 26673 2009-10-01 16:43:13Z matze $
*/
#include "config.h"
#include <stdlib.h>
#include "irprog_t.h"
#include "irgraph_t.h"
#include "irnode_t.h"
#include "irmode_t.h"
#include "ircons_t.h"
#include "iropt_t.h"
#include "irop.h"
#include "irvrfy_t.h"
#include "irprintf.h"
#include "xmalloc.h"
#include "../bearch.h"
#include "amd64_nodes_attr.h"
#include "amd64_new_nodes.h"
#include "gen_amd64_regalloc_if.h"
/**
* Dumper interface for dumping amd64 nodes in vcg.
* @param n the node to dump
* @param F the output file
* @param reason indicates which kind of information should be dumped
* @return 0 on success or != 0 on failure
*/
static int amd64_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
{
ir_mode *mode = NULL;
switch (reason) {
case dump_node_opcode_txt:
fprintf(F, "%s", get_irn_opname(n));
break;
case dump_node_mode_txt:
mode = get_irn_mode(n);
if (mode) {
fprintf(F, "[%s]", get_mode_name(mode));
} else {
fprintf(F, "[?NOMODE?]");
}
break;
case dump_node_nodeattr_txt:
/* TODO: dump some attributes which should show up */
/* in node name in dump (e.g. consts or the like) */
break;
case dump_node_info_txt:
arch_dump_reqs_and_registers(F, n);
break;
}
return 0;
}
const amd64_attr_t *get_amd64_attr_const(const ir_node *node)
{
assert(is_amd64_irn(node) && "need amd64 node to get attributes");
return (const amd64_attr_t *)get_irn_generic_attr_const(node);
}
amd64_attr_t *get_amd64_attr(ir_node *node)
{
assert(is_amd64_irn(node) && "need amd64 node to get attributes");
return (amd64_attr_t *)get_irn_generic_attr(node);
}
static const amd64_immediate_attr_t *get_amd64_immediate_attr_const(const ir_node *node)
{
const amd64_attr_t *attr = get_amd64_attr_const(node);
const amd64_immediate_attr_t *imm_attr = CONST_CAST_AMD64_ATTR(amd64_immediate_attr_t, attr);
return imm_attr;
}
/*
static amd64_immediate_attr_t *get_amd64_immediate_attr(ir_node *node)
{
amd64_attr_t *attr = get_amd64_attr(node);
amd64_immediate_attr_t *imm_attr = CAST_AMD64_ATTR(amd64_immediate_attr_t, attr);
return imm_attr;
}
*/
/**
* Returns the argument register requirements of a amd64 node.
*/
const arch_register_req_t **get_amd64_in_req_all(const ir_node *node)
{
const amd64_attr_t *attr = get_amd64_attr_const(node);
return attr->in_req;
}
/**
* Returns the argument register requirement at position pos of an amd64 node.
*/
const arch_register_req_t *get_amd64_in_req(const ir_node *node, int pos)
{
const amd64_attr_t *attr = get_amd64_attr_const(node);
return attr->in_req[pos];
}
/**
* Sets the IN register requirements at position pos.
*/
void set_amd64_req_in(ir_node *node, const arch_register_req_t *req, int pos)
{
amd64_attr_t *attr = get_amd64_attr(node);
attr->in_req[pos] = req;
}
/**
* Initializes the nodes attributes.
*/
static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags,
const arch_register_req_t **in_reqs,
const be_execution_unit_t ***execution_units,
int n_res)
{
ir_graph *irg = get_irn_irg(node);
struct obstack *obst = get_irg_obstack(irg);
amd64_attr_t *attr = get_amd64_attr(node);
backend_info_t *info;
(void) execution_units;
arch_irn_set_flags(node, flags);
attr->in_req = in_reqs;
info = be_get_info(node);
info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
}
/**
* Initialize immediate attributes.
*/
static void init_amd64_immediate_attributes(ir_node *node, unsigned imm_value)
{
amd64_immediate_attr_t *attr = get_irn_generic_attr (node);
attr->imm_value = imm_value;
}
/** Compare node attributes for Immediates. */
static int cmp_amd64_attr_immediate(ir_node *a, ir_node *b)
{
const amd64_immediate_attr_t *attr_a = get_amd64_immediate_attr_const(a);
const amd64_immediate_attr_t *attr_b = get_amd64_immediate_attr_const(b);
if (attr_a->imm_value != attr_b->imm_value)
return 1;
return 0;
}
static int cmp_amd64_attr(ir_node *a, ir_node *b)
{
const amd64_attr_t *attr_a = get_amd64_attr_const(a);
const amd64_attr_t *attr_b = get_amd64_attr_const(b);
(void) attr_a;
(void) attr_b;
return 0;
}
/* Include the generated constructor functions */
#include "gen_amd64_new_nodes.c.inl"
/*
* 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 Function prototypes for the assembler ir node constructors.
* @version $Id: amd64_new_nodes.h 26549 2009-09-18 17:48:23Z matze $
*/
#ifndef FIRM_BE_TEMPALTE_amd64_NEW_NODES_H
#define FIRM_BE_amd64_amd64_NEW_NODES_H
#include "amd64_nodes_attr.h"
/***************************************************************************************************
* _ _ _ __ _ _ _ _
* | | | | | | / / | | | | | | | |
* __ _| |_| |_ _ __ ___ ___| |_ / /_ _ ___| |_ _ __ ___ ___| |_| |__ ___ __| |___
* / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
* | (_| | |_| |_| | \__ \ __/ |_ / / (_| | __/ |_ | | | | | | __/ |_| | | | (_) | (_| \__ \
* \__,_|\__|\__|_| |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
* __/ |
* |___/
***************************************************************************************************/
/**
* Returns the attributes of an amd64 node.
*/
amd64_attr_t *get_amd64_attr(ir_node *node);
const amd64_attr_t *get_amd64_attr_const(const ir_node *node);
/**
* Returns the argument register requirements of an amd64 node.
*/
const arch_register_req_t **get_amd64_in_req_all(const ir_node *node);
/**
* Returns the argument register requirements of an amd64 node.
*/
const arch_register_req_t *get_amd64_in_req(const ir_node *node, int pos);
/**
* Sets the IN register requirements at position pos.
*/
void set_amd64_req_in(ir_node *node, const arch_register_req_t *req, int pos);
/* Include the generated headers */
#include "gen_amd64_new_nodes.h"
#endif
/*
* 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 attributes attached to all amd64 nodes
* @version $Id: amd64_nodes_attr.h 26317 2009-08-05 10:53:46Z matze $