Commit 1d71000a authored by Matthias Braun's avatar Matthias Braun
Browse files

amd64: rework and fix Const/SymConst nodes

parent 360daec7
...@@ -193,6 +193,22 @@ typedef enum amd64_emit_mod_t { ...@@ -193,6 +193,22 @@ typedef enum amd64_emit_mod_t {
} amd64_emit_mod_t; } amd64_emit_mod_t;
ENUM_BITSET(amd64_emit_mod_t) ENUM_BITSET(amd64_emit_mod_t)
static void amd64_emit_immediate(const amd64_imm_t *const imm)
{
if (imm->symconst != NULL) {
if (imm->sc_sign)
be_emit_char('-');
be_gas_emit_entity(imm->symconst);
}
if (imm->symconst == NULL || imm->offset != 0) {
if (imm->symconst != NULL) {
be_emit_irprintf("%+ld", imm->offset);
} else {
be_emit_irprintf("0x%lX", imm->offset);
}
}
}
void amd64_emitf(ir_node const *const node, char const *fmt, ...) void amd64_emitf(ir_node const *const node, char const *fmt, ...)
{ {
va_list ap; va_list ap;
...@@ -241,9 +257,7 @@ end_of_mods: ...@@ -241,9 +257,7 @@ end_of_mods:
case 'C': { case 'C': {
amd64_attr_t const *const attr = get_amd64_attr_const(node); amd64_attr_t const *const attr = get_amd64_attr_const(node);
/* FIXME: %d is a hack... we must emit 64bit constants, or sign amd64_emit_immediate(&attr->imm);
* extended 32bit constants... */
be_emit_irprintf("$%d", attr->ext.imm_value);
break; break;
} }
...@@ -359,15 +373,6 @@ unknown: ...@@ -359,15 +373,6 @@ unknown:
* *
***********************************************************************************/ ***********************************************************************************/
/**
* Emit a SymConst.
*/
static void emit_amd64_SymConst(const ir_node *irn)
{
const amd64_SymConst_attr_t *attr = get_amd64_SymConst_attr_const(irn);
amd64_emitf(irn, "mov $%E, %D0", attr->entity);
}
/** /**
* Returns the next block in a block schedule. * Returns the next block in a block schedule.
*/ */
...@@ -616,7 +621,6 @@ static void amd64_register_emitters(void) ...@@ -616,7 +621,6 @@ static void amd64_register_emitters(void)
be_set_emitter(op_amd64_Jmp, emit_amd64_Jmp); be_set_emitter(op_amd64_Jmp, emit_amd64_Jmp);
be_set_emitter(op_amd64_LoadZ, emit_amd64_LoadZ); be_set_emitter(op_amd64_LoadZ, emit_amd64_LoadZ);
be_set_emitter(op_amd64_SwitchJmp, emit_amd64_SwitchJmp); be_set_emitter(op_amd64_SwitchJmp, emit_amd64_SwitchJmp);
be_set_emitter(op_amd64_SymConst, emit_amd64_SymConst);
be_set_emitter(op_be_Call, emit_be_Call); be_set_emitter(op_be_Call, emit_be_Call);
be_set_emitter(op_be_Copy, emit_be_Copy); be_set_emitter(op_be_Copy, emit_be_Copy);
be_set_emitter(op_be_CopyKeep, emit_be_Copy); be_set_emitter(op_be_CopyKeep, emit_be_Copy);
......
...@@ -134,7 +134,6 @@ static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags, ...@@ -134,7 +134,6 @@ static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags,
attr->data.ins_permuted = 0; attr->data.ins_permuted = 0;
attr->data.cmp_unsigned = 0; attr->data.cmp_unsigned = 0;
attr->ext.relation = ir_relation_false; attr->ext.relation = ir_relation_false;
attr->ext.imm_value = 0;
} }
/** /**
...@@ -177,13 +176,18 @@ static int cmp_amd64_attr_SymConst(const ir_node *a, const ir_node *b) ...@@ -177,13 +176,18 @@ static int cmp_amd64_attr_SymConst(const ir_node *a, const ir_node *b)
return 0; return 0;
} }
static int cmp_imm(const amd64_imm_t *const imm0, const amd64_imm_t *const imm1)
{
return imm0->offset != imm1->offset || imm0->sc_sign != imm1->sc_sign
|| imm0->symconst != imm1->symconst;
}
/** Compare common amd64 node attributes. */ /** Compare common amd64 node attributes. */
static int cmp_amd64_attr(const ir_node *a, const ir_node *b) static int cmp_amd64_attr(const ir_node *a, const ir_node *b)
{ {
const amd64_attr_t *attr_a = get_amd64_attr_const(a); const amd64_attr_t *attr_a = get_amd64_attr_const(a);
const amd64_attr_t *attr_b = get_amd64_attr_const(b); const amd64_attr_t *attr_b = get_amd64_attr_const(b);
return cmp_imm(&attr_a->imm, &attr_b->imm);
return attr_a->ext.imm_value != attr_b->ext.imm_value;
} }
/** copies the AMD64 attributes of a node. */ /** copies the AMD64 attributes of a node. */
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#ifndef FIRM_BE_AMD64_AMD64_NEW_NODES_H #ifndef FIRM_BE_AMD64_AMD64_NEW_NODES_H
#define FIRM_BE_AMD64_AMD64_NEW_NODES_H #define FIRM_BE_AMD64_AMD64_NEW_NODES_H
#include <stdint.h>
#include "amd64_nodes_attr.h" #include "amd64_nodes_attr.h"
/*************************************************************************************************** /***************************************************************************************************
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#ifndef FIRM_BE_AMD64_AMD64_NODES_ATTR_H #ifndef FIRM_BE_AMD64_AMD64_NODES_ATTR_H
#define FIRM_BE_AMD64_AMD64_NODES_ATTR_H #define FIRM_BE_AMD64_AMD64_NODES_ATTR_H
#include <stdint.h>
#include "bearch.h" #include "bearch.h"
typedef struct amd64_attr_t amd64_attr_t; typedef struct amd64_attr_t amd64_attr_t;
...@@ -23,6 +24,12 @@ typedef enum { ...@@ -23,6 +24,12 @@ typedef enum {
INSN_MODE_8 INSN_MODE_8
} amd64_insn_mode_t; } amd64_insn_mode_t;
typedef struct amd64_imm_t {
int64_t offset;
bool sc_sign;
ir_entity *symconst;
} amd64_imm_t;
struct amd64_attr_t struct amd64_attr_t
{ {
except_attr exc; /**< the exception attribute. MUST be the first one. */ except_attr exc; /**< the exception attribute. MUST be the first one. */
...@@ -35,8 +42,8 @@ struct amd64_attr_t ...@@ -35,8 +42,8 @@ struct amd64_attr_t
} data; } data;
struct amd64_attr_extended { struct amd64_attr_extended {
ir_relation relation; /**< type of compare operation >*/ ir_relation relation; /**< type of compare operation >*/
unsigned imm_value; /**< immediate value to use >*/
} ext; } ext;
amd64_imm_t imm;
}; };
struct amd64_SymConst_attr_t struct amd64_SymConst_attr_t
......
...@@ -212,20 +212,13 @@ Xor => { ...@@ -212,20 +212,13 @@ Xor => {
Const => { Const => {
op_flags => [ "constlike" ], op_flags => [ "constlike" ],
attr => "unsigned imm_value", attr => "amd64_insn_mode_t insn_mode, int64_t offset, bool sc_sign, ir_entity *symconst",
init_attr => "attr->ext.imm_value = imm_value;", init_attr => "attr->imm.offset = offset;\n"
. "attr->imm.sc_sign = sc_sign;\n"
. "attr->imm.symconst = symconst;\n"
. "attr->data.insn_mode = insn_mode;\n",
reg_req => { out => [ "gp" ] }, reg_req => { out => [ "gp" ] },
emit => "mov %C, %D0", emit => 'mov%M $%C, %D0',
mode => $mode_gp,
},
SymConst => {
op_flags => [ "constlike" ],
irn_flags => [ "rematerializable" ],
attr => "ir_entity *entity",
attr_type => "amd64_SymConst_attr_t",
reg_req => { out => [ "gp" ] },
outs => [ "res" ],
mode => $mode_gp, mode => $mode_gp,
}, },
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "iropt_t.h" #include "iropt_t.h"
#include "error.h" #include "error.h"
#include "debug.h" #include "debug.h"
#include "tv_t.h"
#include "benode.h" #include "benode.h"
#include "betranshlp.h" #include "betranshlp.h"
...@@ -37,29 +38,6 @@ static inline int mode_needs_gp_reg(ir_mode *mode) ...@@ -37,29 +38,6 @@ static inline int mode_needs_gp_reg(ir_mode *mode)
return mode_is_int(mode) || mode_is_reference(mode); return mode_is_int(mode) || mode_is_reference(mode);
} }
/**
* Create a DAG constructing a given Const.
*
* @param irn a Firm const
*/
static ir_node *create_const_graph(ir_node *irn, ir_node *block)
{
ir_tarval *tv = get_Const_tarval(irn);
ir_mode *mode = get_tarval_mode(tv);
dbg_info *dbgi = get_irn_dbg_info(irn);
unsigned value;
if (mode_is_reference(mode)) {
/* AMD64 is 64bit, so we can safely convert a reference tarval into Iu */
assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_Lu));
tv = tarval_convert_to(tv, mode_Lu);
}
value = get_tarval_long(tv);
return new_bd_amd64_Const(dbgi, block, value);
}
/* Op transformers: */ /* Op transformers: */
/** /**
...@@ -67,13 +45,18 @@ static ir_node *create_const_graph(ir_node *irn, ir_node *block) ...@@ -67,13 +45,18 @@ static ir_node *create_const_graph(ir_node *irn, ir_node *block)
* *
* @return The transformed AMD64 node. * @return The transformed AMD64 node.
*/ */
static ir_node *gen_Const(ir_node *node) { static ir_node *gen_Const(ir_node *node)
{
ir_node *block = be_transform_node(get_nodes_block(node)); ir_node *block = be_transform_node(get_nodes_block(node));
dbg_info *dbgi = get_irn_dbg_info(node);
ir_mode *mode = get_irn_mode(node); ir_mode *mode = get_irn_mode(node);
ir_node *res = create_const_graph(node, block); if (!mode_needs_gp_reg(mode))
(void) mode; panic("amd64: float constant not supported yet");
ir_tarval *tv = get_Const_tarval(node);
return res; assert(tarval_is_uint64(tv));
uint64_t val = get_tarval_uint64(tv);
amd64_insn_mode_t imode = val > UINT32_MAX ? INSN_MODE_64 : INSN_MODE_32;
return new_bd_amd64_Const(dbgi, block, imode, val, false, NULL);
} }
/** /**
...@@ -84,12 +67,10 @@ static ir_node *gen_Const(ir_node *node) { ...@@ -84,12 +67,10 @@ static ir_node *gen_Const(ir_node *node) {
static ir_node *gen_SymConst(ir_node *node) static ir_node *gen_SymConst(ir_node *node)
{ {
ir_node *block = be_transform_node(get_nodes_block(node)); ir_node *block = be_transform_node(get_nodes_block(node));
ir_entity *entity = get_SymConst_entity(node);
dbg_info *dbgi = get_irn_dbg_info(node); dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *new_node; ir_entity *entity = get_SymConst_entity(node);
new_node = new_bd_amd64_SymConst(dbgi, block, entity); return new_bd_amd64_Const(dbgi, block, INSN_MODE_32, 0, false, entity);
return new_node;
} }
static ir_node *gen_binop(ir_node *const node, ir_node *(*const new_node)(dbg_info*, ir_node*, ir_node*, ir_node*)) static ir_node *gen_binop(ir_node *const node, ir_node *(*const new_node)(dbg_info*, ir_node*, ir_node*, ir_node*))
......
Supports Markdown
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