Commit c3689ef7 authored by Matthias Braun's avatar Matthias Braun
Browse files

cleanup,refactoring of some arm node attribute handling

[r27708]
parent 2f572ce1
......@@ -26,6 +26,7 @@
#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include "xmalloc.h"
#include "tv.h"
......@@ -193,6 +194,16 @@ void arm_emit_mode(const ir_node *node)
arm_emit_fpa_postfix(mode);
}
void arm_emit_symconst(const ir_node *node)
{
const arm_SymConst_attr_t *symconst = get_arm_SymConst_attr_const(node);
ir_entity *entity = symconst->entity;
be_gas_emit_entity(entity);
/* TODO do something with offset */
}
void arm_emit_load_mode(const ir_node *node)
{
const arm_load_store_attr_t *attr = get_arm_load_store_attr_const(node);
......@@ -223,7 +234,7 @@ void arm_emit_store_mode(const ir_node *node)
}
static void emit_shf_mod_name(arm_shift_modifier mod)
static void emit_shf_mod_name(arm_shift_modifier_t mod)
{
switch (mod) {
case ARM_SHF_ASR_REG:
......@@ -298,12 +309,12 @@ void arm_emit_shifter_operand(const ir_node *node)
/** An entry in the sym_or_tv set. */
typedef struct sym_or_tv_t {
union {
ident *id; /**< An ident. */
tarval *tv; /**< A tarval. */
ir_entity *entity; /**< An entity. */
tarval *tv; /**< A tarval. */
const void *generic; /**< For generic compare. */
} u;
unsigned label; /**< the associated label. */
char is_ident; /**< Non-zero if an ident is stored. */
bool is_entity; /**< true if an entity is stored. */
} sym_or_tv_t;
/**
......@@ -324,9 +335,9 @@ static void emit_arm_SymConst(const ir_node *irn)
sym_or_tv_t key, *entry;
unsigned label;
key.u.id = get_entity_ld_ident(attr->entity);
key.is_ident = 1;
key.label = 0;
key.u.entity = attr->entity;
key.is_entity = true;
key.label = 0;
entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
if (entry->label == 0) {
/* allocate a label */
......@@ -337,7 +348,7 @@ static void emit_arm_SymConst(const ir_node *irn)
/* load the symbol indirect */
be_emit_cstring("\tldr ");
arm_emit_dest_register(irn, 0);
be_emit_irprintf(", .L%u", label);
be_emit_irprintf(", %s%u", be_gas_get_private_prefix(), label);
be_emit_finish_line_gas(irn);
}
......@@ -363,9 +374,9 @@ static void emit_arm_fpaConst(const ir_node *irn)
unsigned label;
ir_mode *mode;
key.u.tv = get_fpaConst_value(irn);
key.is_ident = 0;
key.label = 0;
key.u.tv = get_fpaConst_value(irn);
key.is_entity = false;
key.label = 0;
entry = (sym_or_tv_t *)set_insert(sym_or_tv, &key, sizeof(key), HASH_PTR(key.u.generic));
if (entry->label == 0) {
/* allocate a label */
......@@ -380,7 +391,7 @@ static void emit_arm_fpaConst(const ir_node *irn)
be_emit_char(' ');
arm_emit_dest_register(irn, 0);
be_emit_irprintf(", .L%u", label);
be_emit_irprintf(", %s%u", be_gas_get_private_prefix(), label);
be_emit_finish_line_gas(irn);
}
......@@ -422,7 +433,7 @@ static void emit_arm_B(const ir_node *irn)
const ir_node *next_block;
ir_node *op1 = get_irn_n(irn, 0);
const char *suffix;
int proj_num = get_arm_CondJmp_proj_num(irn);
pn_Cmp pnc = get_arm_CondJmp_pnc(irn);
const arm_cmp_attr_t *cmp_attr = get_irn_generic_attr_const(op1);
bool is_signed = !cmp_attr->is_unsigned;
......@@ -439,7 +450,7 @@ static void emit_arm_B(const ir_node *irn)
}
if (cmp_attr->ins_permuted) {
proj_num = get_mirrored_pnc(proj_num);
pnc = get_mirrored_pnc(pnc);
}
/* for now, the code works for scheduled and non-schedules blocks */
......@@ -448,8 +459,8 @@ static void emit_arm_B(const ir_node *irn)
/* we have a block schedule */
next_block = sched_next_block(block);
assert(proj_num != pn_Cmp_False);
assert(proj_num != pn_Cmp_True);
assert(pnc != pn_Cmp_False);
assert(pnc != pn_Cmp_True);
if (get_cfop_target_block(proj_true) == next_block) {
/* exchange both proj's so the second one can be omitted */
......@@ -457,10 +468,10 @@ static void emit_arm_B(const ir_node *irn)
proj_true = proj_false;
proj_false = t;
proj_num = get_negated_pnc(proj_num, mode_Iu);
pnc = get_negated_pnc(pnc, mode_Iu);
}
switch (proj_num) {
switch (pnc) {
case pn_Cmp_Eq: suffix = "eq"; break;
case pn_Cmp_Lt: suffix = is_signed ? "lt" : "lo"; break;
case pn_Cmp_Le: suffix = is_signed ? "le" : "ls"; break;
......@@ -1141,11 +1152,12 @@ void arm_gen_routine(const arm_code_gen_t *arm_cg, ir_graph *irg)
be_emit_cstring("\t.align 2\n");
foreach_set(sym_or_tv, entry) {
be_emit_irprintf(".L%u:\n", entry->label);
be_emit_irprintf("%s%u:\n", be_gas_get_private_prefix(),
entry->label);
if (entry->is_ident) {
if (entry->is_entity) {
be_emit_cstring("\t.word\t");
be_emit_ident(entry->u.id);
be_gas_emit_entity(entry->u.entity);
be_emit_char('\n');
be_emit_write_line();
} else {
......
......@@ -36,6 +36,7 @@
#include "bearch_arm_t.h"
void arm_emit_mode(const ir_node *node);
void arm_emit_symconst(const ir_node *node);
void arm_emit_source_register(const ir_node *node, int pos);
void arm_emit_dest_register(const ir_node *node, int pos);
void arm_emit_offset(const ir_node *node);
......
......@@ -28,6 +28,7 @@
#include "config.h"
#include <stdlib.h>
#include <stdbool.h>
#include "irprog_t.h"
#include "irgraph_t.h"
......@@ -49,9 +50,6 @@
#include "../beabi.h"
#include "bearch_arm_t.h"
/**
* Return the fpa immediate from the encoding.
*/
const char *arm_get_fpa_imm_name(long imm_value)
{
static const char *fpa_imm[] = {
......@@ -67,6 +65,28 @@ const char *arm_get_fpa_imm_name(long imm_value)
return fpa_imm[imm_value];
}
static bool arm_has_immediate(const ir_node *node)
{
return is_arm_SymConst(node) || is_arm_FrameAddr(node);
}
static bool has_load_store_attr(const ir_node *node)
{
return is_arm_Ldr(node) || is_arm_Str(node);
}
static bool has_shifter_operand(const ir_node *node)
{
return is_arm_Add(node) || is_arm_And(node) || is_arm_Or(node)
|| is_arm_Eor(node) || is_arm_Bic(node) || is_arm_Sub(node)
|| is_arm_Rsb(node) || is_arm_Mov(node) || is_arm_Mvn(node)
|| is_arm_Cmp(node) || is_arm_Tst(node);
}
static bool has_cmp_attr(const ir_node *node)
{
return is_arm_Cmp(node) || is_arm_Tst(node);
}
/**
* Dumper interface for dumping arm nodes in vcg.
......@@ -76,57 +96,99 @@ const char *arm_get_fpa_imm_name(long imm_value)
*/
static void arm_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
{
ir_mode *mode = NULL;
//arm_attr_t *attr = get_arm_attr(n);
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));
case dump_node_opcode_txt:
fprintf(F, "%s", get_irn_opname(n));
if (arm_has_immediate(n)) {
const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(n);
if (attr->entity != NULL) {
fputc(' ', F);
fputs(get_entity_name(attr->entity), F);
}
else {
fprintf(F, "[?NOMODE?]");
}
break;
case dump_node_mode_txt:
/* mode isn't relevant in the backend */
break;
case dump_node_nodeattr_txt:
/* TODO: dump shift modifiers */
break;
case dump_node_info_txt:
arch_dump_reqs_and_registers(F, n);
if (has_load_store_attr(n)) {
const arm_load_store_attr_t *attr
= get_arm_load_store_attr_const(n);
ir_fprintf(F, "load_store_mode = %+F\n", attr->load_store_mode);
ir_fprintf(F, "entity = %+F\n", attr->entity);
fprintf(F, "offset = %ld\n", attr->offset);
fprintf(F, "is_frame_entity = %s\n",
attr->is_frame_entity ? "yes" : "no");
fprintf(F, "entity_sign = %s\n",
attr->entity_sign ? "yes" : "no");
}
if (has_shifter_operand(n)) {
const arm_shifter_operand_t *attr
= get_arm_shifter_operand_attr_const(n);
switch (attr->shift_modifier) {
case ARM_SHF_REG:
break;
case ARM_SHF_IMM:
fprintf(F, "modifier = imm %d ror %d\n",
attr->immediate_value, attr->shift_immediate);
break;
case ARM_SHF_ASR_IMM:
fprintf(F, "modifier = V >>s %d\n", attr->shift_immediate);
break;
case ARM_SHF_ASR_REG:
fprintf(F, "modifier = V >>s R\n");
break;
case ARM_SHF_LSL_IMM:
fprintf(F, "modifier = V << %d\n", attr->shift_immediate);
break;
case ARM_SHF_LSL_REG:
fprintf(F, "modifier = V << R\n");
break;
case ARM_SHF_LSR_IMM:
fprintf(F, "modifier = V >> %d\n", attr->shift_immediate);
break;
case ARM_SHF_LSR_REG:
fprintf(F, "modifier = V >> R\n");
break;
case ARM_SHF_ROR_IMM:
fprintf(F, "modifier = V ROR %d\n", attr->shift_immediate);
break;
case ARM_SHF_ROR_REG:
fprintf(F, "modifier = V ROR R\n");
break;
case ARM_SHF_RRX:
fprintf(F, "modifier = RRX\n");
break;
default:
case ARM_SHF_INVALID:
fprintf(F, "modifier = INVALID SHIFT MODIFIER\n");
break;
}
break;
case dump_node_nodeattr_txt:
/* TODO: dump shift modifiers */
break;
case dump_node_info_txt:
arch_dump_reqs_and_registers(F, n);
if (is_arm_CopyB(n)) {
//fprintf(F, "size = %lu\n", get_arm_imm_value(n));
} else {
/* TODO */
#if 0
long v = get_arm_imm_value(n);
if (ARM_GET_FPA_IMM(attr)) {
fprintf(F, "immediate float value = %s\n", arm_get_fpa_imm_name(v));
} else {
fprintf(F, "immediate value = %ld (0x%08lx)\n", v, v);
}
#endif
}
if (has_cmp_attr(n)) {
const arm_cmp_attr_t *attr = get_arm_cmp_attr_const(n);
fprintf(F, "cmp_attr =");
if (attr->is_unsigned) {
fprintf(F, " unsigned");
}
#if 0
if (is_arm_CmpBra(n) && get_arm_CondJmp_proj_num(n) >= 0) {
fprintf(F, "proj_num = (%d)\n", get_arm_CondJmp_proj_num(n));
if (attr->ins_permuted) {
fprintf(F, " inputs swapped");
}
#endif
break;
fprintf(F, "\n");
}
break;
}
}
/* Returns the attributes of a generic Arm node. */
arm_attr_t *get_arm_attr(ir_node *node)
{
assert(is_arm_irn(node) && "need arm node to get attributes");
......@@ -139,22 +201,25 @@ const arm_attr_t *get_arm_attr_const(const ir_node *node)
return get_irn_generic_attr_const(node);
}
/**
* Returns the attributes of an ARM SymConst node.
*/
static bool has_symconst_attr(const ir_node *node)
{
return is_arm_SymConst(node) || is_arm_FrameAddr(node);
}
arm_SymConst_attr_t *get_arm_SymConst_attr(ir_node *node)
{
assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
assert(has_symconst_attr(node));
return get_irn_generic_attr(node);
}
const arm_SymConst_attr_t *get_arm_SymConst_attr_const(const ir_node *node)
{
assert(is_arm_SymConst(node) || is_arm_FrameAddr(node));
assert(has_symconst_attr(node));
return get_irn_generic_attr_const(node);
}
static const arm_fpaConst_attr_t *get_arm_fpaConst_attr_const(const ir_node *node)
static const arm_fpaConst_attr_t *get_arm_fpaConst_attr_const(
const ir_node *node)
{
const arm_attr_t *attr = get_arm_attr_const(node);
const arm_fpaConst_attr_t *fpa_attr = CONST_CAST_ARM_ATTR(arm_fpaConst_attr_t, attr);
......@@ -170,7 +235,6 @@ static arm_fpaConst_attr_t *get_arm_fpaConst_attr(ir_node *node)
return fpa_attr;
}
/* Returns the attributes of a CondJmp node. */
arm_CondJmp_attr_t *get_arm_CondJmp_attr(ir_node *node)
{
assert(is_arm_B(node));
......@@ -183,7 +247,6 @@ const arm_CondJmp_attr_t *get_arm_CondJmp_attr_const(const ir_node *node)
return get_irn_generic_attr_const(node);
}
/* Returns the attributes of a SwitchJmp node. */
arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr(ir_node *node)
{
assert(is_arm_SwitchJmp(node));
......@@ -196,99 +259,66 @@ const arm_SwitchJmp_attr_t *get_arm_SwitchJmp_attr_const(const ir_node *node)
return get_irn_generic_attr_const(node);
}
/**
* Returns the argument register requirements of a arm node.
*/
const arch_register_req_t **get_arm_in_req_all(const ir_node *node)
void set_arm_in_req_all(ir_node *node, const arch_register_req_t **reqs)
{
const arm_attr_t *attr = get_arm_attr_const(node);
return attr->in_req;
arm_attr_t *attr = get_arm_attr(node);
attr->in_req = reqs;
}
/**
* Returns the argument register requirement at position pos of an arm node.
*/
const arch_register_req_t *get_arm_in_req(const ir_node *node, int pos)
{
const arm_attr_t *attr = get_arm_attr_const(node);
return attr->in_req[pos];
}
/**
* Sets the IN register requirements at position pos.
*/
void set_arm_req_in(ir_node *node, const arch_register_req_t *req, int pos)
{
arm_attr_t *attr = get_arm_attr(node);
attr->in_req[pos] = req;
}
/**
* Returns the fpaConst value
*/
tarval *get_fpaConst_value(const ir_node *node)
{
const arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr_const(node);
return attr->tv;
}
/**
* Sets the tarval value
*/
void set_fpaConst_value(ir_node *node, tarval *tv)
{
arm_fpaConst_attr_t *attr = get_arm_fpaConst_attr(node);
attr->tv = tv;
}
/**
* Returns the proj num
*/
int get_arm_CondJmp_proj_num(const ir_node *node)
pn_Cmp get_arm_CondJmp_pnc(const ir_node *node)
{
const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
return attr->proj_num;
return attr->pnc;
}
/**
* Sets the proj num
*/
void set_arm_CondJmp_proj_num(ir_node *node, int proj_num)
void set_arm_CondJmp_pnc(ir_node *node, pn_Cmp pnc)
{
arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
attr->proj_num = proj_num;
attr->pnc = pnc;
}
/**
* Returns the number of projs of a SwitchJmp.
*/
int get_arm_SwitchJmp_n_projs(const ir_node *node)
{
const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
return attr->n_projs;
}
/**
* Sets the number of projs.
*/
void set_arm_SwitchJmp_n_projs(ir_node *node, int n_projs)
{
arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
attr->n_projs = n_projs;
}
/**
* Returns the default_proj_num.
*/
long get_arm_SwitchJmp_default_proj_num(const ir_node *node)
{
const arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr_const(node);
return attr->default_proj_num;
}
/**
* Sets the default_proj_num.
*/
void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num)
{
arm_SwitchJmp_attr_t *attr = get_arm_SwitchJmp_attr(node);
......@@ -331,7 +361,7 @@ static void init_arm_load_store_attributes(ir_node *res, ir_mode *ls_mode,
}
static void init_arm_shifter_operand(ir_node *res, unsigned immediate_value,
arm_shift_modifier shift_modifier,
arm_shift_modifier_t shift_modifier,
unsigned shift_immediate)
{
arm_shifter_operand_t *attr = get_irn_generic_attr(res);
......@@ -347,11 +377,12 @@ static void init_arm_cmp_attr(ir_node *res, bool ins_permuted, bool is_unsigned)
attr->is_unsigned = is_unsigned;
}
static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity)
static void init_arm_SymConst_attributes(ir_node *res, ir_entity *entity,
int symconst_offset)
{
arm_SymConst_attr_t *attr = get_irn_generic_attr(res);
attr->entity = entity;
attr->fp_offset = 0;
attr->fp_offset = symconst_offset;
}
static void init_arm_CopyB_attributes(ir_node *res, unsigned size)
......@@ -440,6 +471,22 @@ arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node)
return (arm_shifter_operand_t*) get_irn_generic_attr(node);
}
const arm_shifter_operand_t *get_arm_shifter_operand_attr_const(
const ir_node *node)
{
return (const arm_shifter_operand_t*) get_irn_generic_attr_const(node);
}
arm_cmp_attr_t *get_arm_cmp_attr(ir_node *node)
{
return (arm_cmp_attr_t*) get_irn_generic_attr(node);
}
const arm_cmp_attr_t *get_arm_cmp_attr_const(const ir_node *node)
{
return (const arm_cmp_attr_t*) get_irn_generic_attr_const(node);
}
static int cmp_attr_arm_load_store(ir_node *a, ir_node *b)
{
const arm_load_store_attr_t *attr_a;
......@@ -511,6 +558,5 @@ static void arm_copy_attr(ir_graph *irg, const ir_node *old_node,
}
/* Include the generated constructor functions */
#include "gen_arm_new_nodes.c.inl"
......@@ -57,11 +57,12 @@ arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node);
const arm_load_store_attr_t *get_arm_load_store_attr_const(const ir_node *node);
arm_shifter_operand_t *get_arm_shifter_operand_attr(ir_node *node);
const arm_shifter_operand_t *get_arm_shifter_operand_attr_const(const ir_node *node);
/**
* Returns the argument register requirements of an arm node.
*/
const arch_register_req_t **get_arm_in_req_all(const ir_node *node);
arm_cmp_attr_t *get_arm_cmp_attr(ir_node *node);
const arm_cmp_attr_t *get_arm_cmp_attr_const(const ir_node *node);
void set_arm_in_req_all(ir_node *node, const arch_register_req_t **reqs);
/**
* Returns the argument register requirements of an arm node.
......@@ -84,14 +85,14 @@ tarval *get_fpaConst_value(const ir_node *node);
void set_fpaConst_value(ir_node *node, tarval *tv);
/**
* Returns the proj num
* Returns the compare kind
*/
int get_arm_CondJmp_proj_num(const ir_node *node);
pn_Cmp get_arm_CondJmp_pnc(const ir_node *node);
/**
* Sets the proj num
* Set compare type
*/
void set_arm_CondJmp_proj_num(ir_node *node, int proj_num);
void set_arm_CondJmp_pnc(ir_node *node, pn_Cmp pnc);
ir_node *new_r_arm_StoreStackMInc(ir_graph *irg, ir_node *block, ir_node *mem, ir_node *sp,
int n_regs, ir_node **regs, ir_mode *mode);
......
......@@ -33,7 +33,7 @@
/**
* Possible ARM "shifter operand" addressing mode types.
*/
typedef enum _arm_shift_modifier {
typedef enum arm_shift_modifier_t {
ARM_SHF_INVALID, /**< invalid shift */
ARM_SHF_REG, /**< simple register operand */
ARM_SHF_IMM, /**< immediate operand with implicit ROR */
......@@ -46,7 +46,7 @@ typedef enum _arm_shift_modifier {
ARM_SHF_ROR_IMM, /**< rotate right */
ARM_SHF_ROR_REG, /**< rotate right */
ARM_SHF_RRX, /**< rotate right through carry bits */
} arm_shift_modifier;
} arm_shift_modifier_t;
/** fpa immediate bit */
#define ARM_FPA_IMM (1 << 3) /**< fpa floating point immediate */
......@@ -69,7 +69,7 @@ enum fpa_immediates {
};
/** Generic ARM node attributes. */
typedef struct _arm_attr_t {
typedef struct arm_attr_t {
except_attr exc; /**< the exception attribute. MUST be the first one. */
const arch_register_req_t **in_req; /**< register requirements for arguments */
......@@ -84,10 +84,10 @@ typedef struct _arm_attr_t {
* "data processing operands" also called "shifter operand" addressing modes
*/
typedef struct arm_shifter_operand_t {
arm_attr_t base;
arm_shift_modifier shift_modifier;
unsigned char immediate_value;
unsigned char shift_immediate;
arm_attr_t base;
arm_shift_modifier_t shift_modifier;
unsigned char immediate_value;
unsigned char shift_immediate;
} arm_shifter_operand_t;